What are some useful constructs for using XSLT to create XSLT?

I have an existing XSLT stylesheet that takes XML and creates beautifully formatted XHTML. I want to make an XSL-FO version of this stylesheet to create a PDF file through Apache FOP. I want to know the following:

Is it possible to use xslt templates, I need to learn how to do things like:

  • copying some nodes without changes
  • copying most of the node, but adding extra attributes

I know that I can create new nodes with

<xsl:element>

but are there any other useful things that I will need. Please note that although I did not make many copies from one XSLT format to another, I did TONS XML-> XHTML through XSLT, so I am familiar with most of the core language.

+3
source share
3 answers

The pattern you are looking for is a “modified identity transformation”. The basis of this approach is the identity transformation rule, the first rule of the template in the stylesheet below. Each rule then represents an exception from copy mode.

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- By default, copy all nodes unchanged -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- But strip out <foo> elements (including their content) -->
  <xsl:template match="foo"/>

  <!-- For <bar> elements, strip out start & end tags, but leave content --> 
  <xsl:template match="bar">
    <xsl:apply-templates/>
  </xsl:template>

  <!-- For <bat> elements, insert an attribute and append a child --> 
  <xsl:template match="bat">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:attribute name="id">123</xsl:attribute>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

What suits me the least is the duplication of logic found in the last rule of the template. This is a lot of code for just adding a single attribute. And imagine if we need a bunch of them. Here is another approach that allows us to be more quickly accurate in what we want to redefine:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- By default, copy all nodes unchanged -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates mode="add-atts" select="."/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

          <!-- By default, don't add any attributes -->
          <xsl:template mode="add-atts" match="*"/>

  <!-- For <bat> elements, insert an "id" attribute -->
  <xsl:template mode="add-atts" match="bat">
    <xsl:attribute name="id">123</xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

, , , , , :

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- For <bat> elements, insert an "id" attribute -->
  <xsl:template mode="add-atts" match="bat">
    <xsl:attribute name="id">123</xsl:attribute>
  </xsl:template>

  <!-- Append <new-element/> to <bat> -->
  <xsl:template mode="append" match="bat">
    <new-element/>
  </xsl:template>

  <!-- Insert an element in <foo> content -->
  <xsl:template mode="insert" match="foo">
    <inserted/>
  </xsl:template>

  <!-- Add content before the <bar/> and <bat/> elements -->
  <xsl:template mode="before" match="bar | bat">
    <before-bat-and-bar/>
  </xsl:template>

  <!-- Add content only after <bat/> -->
  <xsl:template mode="after" match="bat">
    <after-bat/>
  </xsl:template>

  <!-- Here the boilerplate code -->
  <!-- By default, copy all nodes unchanged -->
  <xsl:template match="@* | node()">
    <xsl:apply-templates mode="before" select="."/>
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates mode="add-atts" select="."/>
      <xsl:apply-templates mode="insert" select="."/>
      <xsl:apply-templates/>
      <xsl:apply-templates mode="append" select="."/>
    </xsl:copy>
    <xsl:apply-templates mode="after" select="."/>
  </xsl:template>

          <!-- By default, don't add anything -->
          <xsl:template mode="add-atts" match="*"/>
          <xsl:template mode="insert"   match="*"/>
          <xsl:template mode="append"   match="*"/>
          <xsl:template mode="before"   match="@* | node()"/>
          <xsl:template mode="after"    match="@* | node()"/>

</xsl:stylesheet>

XSLT 2.0 :

          <!-- By default, don't add anything -->
          <xsl:template mode="add-atts
                              insert
                              append
                              before
                              after" match="@* | node()"/>

, - .

+8

XSLT , XSL . "xsl:" XSL, , XSLT XSL, , , , XSLT . , :

<xsl:namespace-alias stylesheet-prefix="x" result-prefix="xsl"/>

, <xsl:stylesheet />, , . , , , , aliass. , , , :

<xsl:template match="xsl:template[@match='title']>
   <x:template match="title>
      <x:apply-templates />
   </x:template>
</xsl:template>

: http://www.xml.com/pub/a/2001/04/04/trxml/

+3

XSL-FO, Render-X FO2HTML , XSL-FO HTML, <block> <div>, <inline> <span> ..

, HTML2FO. , , , .

HTML , FO, , XSL-FO, , , HTML XSL-FO/ .

0

Source: https://habr.com/ru/post/1709796/


All Articles