使用XSLT生成XSLT有哪些有用的结构?

Jay*_*ens 3 xml xslt xsl-fo xslt-2.0

我有一个现有的XSLT样式表,它采用XML并生成格式良好的XHTML.我想制作这个样式表的XSL-FO版本,通过Apache FOP生成PDF.我想知道的是:

有没有方便使用xslt模式我需要学习做以下事情:

  • 复制一些节点不变
  • 复制大部分节点,但添加额外的属性

我知道我可以使用创建新节点

<xsl:element>
Run Code Online (Sandbox Code Playgroud)

但是我还需要其他有用的东西吗?请注意,虽然我没有从一种XSLT格式复制到另一种格式,但我已经通过XSLT完成了XML-> XHTML,因此我熟悉该语言的大部分内核.

Eva*_*enz 8

您正在寻找的模式是"修改后的身份转换".此方法的基础是身份转换规则,即下面样式表中的第一个模板规则.之后的每个规则都代表复制行为的一个例外.

<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>
Run Code Online (Sandbox Code Playgroud)

对我来说最不满意的是上一个模板规则中的重复逻辑.这只是添加一个属性的很多代码.想象一下,如果我们需要一堆这些.这是另一种方法,它允许我们在我们想要覆盖的内容中更加精确地进行手术:

<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>
Run Code Online (Sandbox Code Playgroud)

最后,对于您可能想要进行的每种编辑,可以使用不同的模式进一步执行此操作:

<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's 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>
Run Code Online (Sandbox Code Playgroud)

在XSLT 2.0中,由于多模式模板规则,一些样板可以略微简化:

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

我有时会在同一样式表中使用所有这些自定义模式,但通常我会根据需要懒得添加它们.