如何限制key()在子节点而不是整个xml中搜索

时间:2017-03-24 10:25:27

标签: xml xslt xslt-1.0

XSLT 1.0中是否有任何方法限制函数key()在子节点内搜索而不是整个输入XML。 我的输入XML是

    <a>
    <b>
        <c>
            <d name="1"/>
            <d name="2"/>
            <d name="3"/>
            <d name="1"/>
        </c>
    </b>
    <b>
        <c>
            <d name="1"/>
            <d name="2"/>
        </c>
    </b>
</a>

我写的XSLT是

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

<xsl:key name="findD" match="d" use="@name"/>

<xsl:template match="/">
    <start>
        <xsl:apply-templates select="a/b/c"/>
    </start>
</xsl:template>

<xsl:template match="a/b/c">
    <inside>
        <xsl:for-each select="key('findD', '1')">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </inside>
</xsl:template>

结果是

    <?xml version='1.0' ?>
<start>
    <inside>
        <d name="1"/>
        <d name="1"/>
        <d name="1"/>
    </inside>
    <inside>
        <d name="1"/>
        <d name="1"/>
        <d name="1"/>
    </inside>
</start> 

我需要的是像

     <?xml version='1.0' ?>
<start>
    <inside>
        <d name="1"/>
        <d name="1"/>
    </inside>
    <inside>
        <d name="1"/>
    </inside>
</start> 

这将返回所有三个节点&#39; d&#39; (每个c节点存在于xml中)。虽然我需要的是在相应的c节点内获取d个节点(当调用密钥时)。

我已经看到在key()中使用concat,其中可以根据节点c的值来连接结果。有没有其他方法可以说key()只在一个节点内查看,而不是整个XML。

1 个答案:

答案 0 :(得分:0)

以下是答案:

<xsl:key name="findD" match="d" use="generate-id(..)"/>

<xsl:template match="/">
  <start>
    <xsl:apply-templates select="a/b/c"/>
  </start>
</xsl:template>

<xsl:template match="a/b/c">
  <xsl:variable name="parentID" select="generate-id(.)"/>
  <inside>
    <xsl:for-each select="key('findD', $parentID)[@name='1']">
      <xsl:copy-of select="."/>
    </xsl:for-each>
  </inside>
</xsl:template>

请告诉我们您为什么要在这里使用密钥。只需使用正常的推送编程就可以非常有效和直接地解决这个问题。

<xsl:template match="/">
  <start>
    <xsl:apply-templates select="a/b/c"/>
  </start>
</xsl:template>

<xsl:template match="c">
  <inside>
    <xsl:apply-templates select="d[@name='1']"/>
  </inside>
</xsl:template>

<xsl:template match="d">
  <xsl:copy-of select="."/>
</xsl:template>