Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
xslt 1.0,使用键选择节点组_Xslt_Grouping_Xslt 1.0_Muenchian Grouping_Xslkey - Fatal编程技术网

xslt 1.0,使用键选择节点组

xslt 1.0,使用键选择节点组,xslt,grouping,xslt-1.0,muenchian-grouping,xslkey,Xslt,Grouping,Xslt 1.0,Muenchian Grouping,Xslkey,我想根据一些变量选择节点。 XML代码: <data> <prot seq="AAA"> <node num="1">1345</node> <node num="1">11245</node> <node num="2">88885</node> </

我想根据一些变量选择节点。 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>

1345
11245
88885
678
456
6666
111
222
333
我想要的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>

1345
88885
678
6666
111
333
因此,我的想法是使用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>

节点1345
节点1345
节点678
节点678
节点111
节点111
以及要测试的代码


谢谢

代码中的主要问题是关键索引
prot
元素,但我们要消除重复(并且需要索引)的是
节点
元素

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

<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>
<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>

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

<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>
<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>

1345
11245
88885
678
456
6666
111
222
333
生成所需的正确结果

<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>
<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>

1345
88885
678
6666
111
333

作为旁注——一定要使用一个真正的XSLT处理器,而不是一些“蛋糕”,它们可能在需要时随时可用,也可能不可用,而且可能有很多问题。我推荐的好的XSLT处理器有:(XSLT1.0)MSXML3,4,6、Saxon 6.5.4、.NET XslCompiledTransform、AltovaXML。(XSLT 2.0)Saxon 9.xx、XQSharp、AltovaXML。我正在研究这个主题,这就是为什么我还没有回答。但是,关于您的答案,您是否参考web客户端xsltcake来进行测试?我在代码中使用的处理器是firefox,我主要使用这个web应用程序来简化问题,如果我不能解决问题,就把它发布在这里。Gerard,我不会向任何朋友推荐xslcake——它是测试版的,不可靠(可能在任何时候都不可用——一次基本的DOS攻击会让它长期失效),它使用不同的XSLT处理器产生不同的结果(取决于发送请求的浏览器),有时会产生荒谬的结果。作者自己警告他们的用户这个应用程序的状态和有用性。我建议使用一个好的XSLT IDE,比如XSelerator或at list Kernow。实际上,由于我的处理器将是firefox,所以xsltcake使用相同的处理器是合适的(只要我使用firefox访问它)。但关于它的阿尔法状态你是对的。对我来说,不安装任何东西就可以使用它是一个非常有用的功能。也许在更成熟的状态下还有更多类似的web服务吗?没有,我想主要原因是,这是对DOS攻击的邀请。