应用的模板无法将规则与多个谓词匹配

时间:2017-03-08 08:40:55

标签: xml xslt xpath xslt-2.0

我一直在尝试复制节点并更改其属性。基本上,我希望<parent id="1">也有一个<child id="3">并在其中添加一个属性,在本文档中:

 <container>
  <parent id="1">
    <child id="1"/>
    <child id="2"/>
  </parent>
  <parent id="2">
    <child id="1"/>
    <child id="2"/>
    <child id="3" attrs="I am special"/>
  </parent>
</container>

生成的文档如下所示:

 <container>
  <parent id="1">
    <child id="1"/>
    <child id="2"/>
    <child id="3" attrs="I am special" cloned="I have been cloned"/>
  </parent>
  <parent id="2">
    <child id="1"/>
    <child id="2"/>
    <child id="3" attrs="I am special"/>
  </parent>
</container>

要复制孩子,我只需选择我想要填充的parentapply-templates以及他想要的对象:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="parent[@id='1']/child[last()]">
    <xsl:call-template name="identity"/>
    <xsl:apply-templates select="//*/child[@id='3']"/>
  </xsl:template>
</xsl:stylesheet>

随着副本的处理,我一直试图改变属性,但无济于事。没有任何内容匹配,并且未使用以下模板添加该属性:

<xsl:template match="child[@id='3' and ../@id='1']">
  <xsl:apply-templates select="@*|node()" />
  <xsl:attribute name="clone">I have been cloned</xsl:attribute>
</xsl:template>

由于我对XSLT的理解有限,这将在apply-templates期间触发,本来会复制节点并添加我的属性。输出另有说明:child id="3"被复制,但没有属性的标志。

我想也许新添加的节点还没有“可访问”,或类似的东西,但是一个简单的规则会匹配它(这不好,因为它修改了我正在复制的原始节点):

<xsl:template match="child[@id='3']">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()" />
    <xsl:attribute name="att1">I have been cloned?!</xsl:attribute>
  </xsl:copy>
</xsl:template>

我以为我可能一直在弄乱谓词,但添加一个带有类似谓词的属性(减去前一个副本)就像一个魅力:

  <xsl:template match="child[@id='1' and ../@id='1']">
  <xsl:copy>
    <xsl:attribute name="clone">Nope, just a normal kid</xsl:attribute>
    <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
</xsl:template>

我还认为我的“复制”模板可能与更高的优先级匹配,但是优先级的播放也无济于事。

我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

新元素是结果树的一部分,您无法在同一转换步骤中匹配它。我建议使用一种模式来改变要添加的元素的处理:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

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

  <xsl:template match="parent[@id='1']/child[last()]">
    <xsl:next-match/>
    <xsl:apply-templates select="//*/child[@id='3']" mode="add-att"/>
  </xsl:template>

<xsl:template match="child[@id='3']" mode="add-att">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:attribute name="att1">I have been cloned?!</xsl:attribute>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

</xsl:transform>

http://xsltransform.net/ncntCTd在线。