XSLT复制全部并替换条件

时间:2017-04-10 13:18:09

标签: xml xslt

我需要一个XSLT转换,它将整个输入文档复制到输出文档,如果输入文档不包含该元素,则插入一个具有默认值的特定元素。

具体来说,我想转换这种一般形式的输入XML

/Begin/tag1

自身,但如果输入没有<Begin> <tag2>c</tag2> </Begin> ,那么我想提供一个。也就是说,我想转换

<Begin>
    <tag1>x</tag1>
    <tag2>c</tag2>
</Begin>

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

这是我目前的XSLT:

<tag1>

它复制整个输入文档,但不提供默认的<xsl:choose>元素。我无法在该样式表中的模板中使用<tag1>,因为它会将choose插入到没有一个的永久元素中,并且我不能在{/ 1}} 之后放置 em>模板,因为它无效。如何为<tag1>元素提供默认的<Begin>元素

2 个答案:

答案 0 :(得分:1)

如果模板没有Begin,您可以添加与tag1匹配的模板并插入tag1。请注意,这适用于您非常简单的示例,但如果您有一个更复杂的情况,需要插入大量元素或多个元素,那么解决方案可能会变得更加复杂。

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Begin[not(tag1)]">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <tag1>x</tag1>
      <xsl:apply-templates select="node()" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

您是正确的,不能将<xsl:choose>元素放在模板之外。 XSL通过转换输入文档的节点来运行;您只能根据特定节点的转换方式来表达转换的细节 - 即通过模板。

此外,通过提供替代模板或select表达式来表达替代方案通常比在模板中使用<xsl:choose> <xsl:if>等逻辑元素更自然。

在这种情况下,您有两种选择:

  1. 输入文档的/Begin元素有一个tag1孩子
  2. 输入文档的/Begin元素没有tag1孩子
  3. 在第一种情况下,你不需要做任何特别的事情 - 你已经写过的身份变换会做正确的事情。那么,您所需要的只是处理后一种选择的合适模板。只要它具有比身份变换更高的优先级,它将用于Begin元素而不是身份变换,无论它适用于何处。

    例如,

    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:template match="node()|@*">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="Begin[count(tag1) = 0]">
        <xsl:copy>
          <tag1>x</tag1>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    请注意添加的模板,该模板仅适用于没有Begin子元素的<tag1>元素。它复制整个元素及其子节点,但也插入<tag1>