xslt 1.0,用键选择一组节点



我想根据一些变量选择节点。XML代码:

<data>
    <prot seq="AAA">
        <node num="1">1345</node>
        <node num="1">11245</node>
        <node num="2">88885</node>
    </prot>
    <prot seq="BBB">
        <node num="1">678</node>
        <node num="1">456</node>
        <node num="2">6666</node>
    </prot>
    <prot seq="CCC">
        <node num="1">111</node>
        <node num="1">222</node>
        <node num="2">333</node>
    </prot>
</data>

我想要的XML

<output>
    <prot seq="AAA">
        <node num="1">1345</node>
        <node num="2">88885</node>
    </prot>
    <prot seq="BBB">
        <node num="1">678</node>
        <node num="2">6666</node>
    </prot>
    <prot seq="CCC">
        <node num="1">111</node>
        <node num="2">333</node>
    </prot>
</data>

因此,我的想法是用xsl:key元素对节点进行分组,然后为每个节点做一个。例如:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:key name="by" match="/data/prot" use="concat(@seq,'|',node/@num)"/>
    <xsl:template match="/">
        <root>
            <xsl:apply-templates select="/data/prot"/>
        </root>
    </xsl:template>
    <xsl:template match="/data/prot">
        <xsl:for-each select="./node">
            <xsl:for-each select="key('by',concat(current()/../@seq,'|',current()/@num))">
                node <xsl:value-of select="./node" />
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

但输出并不是我所期望的,我看不出我做错了什么。我更愿意保留每个结构的。就好像我没有正确使用xsl:key分组功能一样。

我得到的输出,不需要的

<root>
    node 1345
    node 1345
    node 678
    node 678
    node 111
node 111</root>

以及待测试的代码http://www.xsltcake.com/slices/sgWUFu/20

谢谢!

代码中的主要问题是键对prot元素进行索引,但我们想要消除重复(并且需要索引)的是node元素

这里有一个简短而正确的解决方案

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:key name="nodeByParentAndNum" match="node"
  use="concat(generate-id(..), '+', @num)"/>
 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="/*">
  <data>
   <xsl:apply-templates/>
  </data>
 </xsl:template>
 <xsl:template match=
 "node
   [not(generate-id()
       =
        generate-id(key('nodeByParentAndNum',
                        concat(generate-id(..), '+', @num)
                        )
                         [1]
                    )
       )
   ]
 "/> 
</xsl:stylesheet>

当此转换应用于所提供的XML文档时

<data>
    <prot seq="AAA">
        <node num="1">1345</node>
        <node num="1">11245</node>
        <node num="2">88885</node>
    </prot>
    <prot seq="BBB">
        <node num="1">678</node>
        <node num="1">456</node>
        <node num="2">6666</node>
    </prot>
    <prot seq="CCC">
        <node num="1">111</node>
        <node num="1">222</node>
        <node num="2">333</node>
    </prot>
</data>

生成所需的正确结果

<data>
   <prot seq="AAA">
      <node num="1">1345</node>
      <node num="2">88885</node>
   </prot>
   <prot seq="BBB">
      <node num="1">678</node>
      <node num="2">6666</node>
   </prot>
   <prot seq="CCC">
      <node num="1">111</node>
      <node num="2">333</node>
   </prot>
</data>

相关内容

  • 没有找到相关文章

最新更新