我有两个不同的节点集,其中包含一个或多个具有相同名称的元素。
我想通过在XPath 2.0和XPath 1.0中使用相交操作来选择这些同名元素。
这是我尝试过的示例代码。
输入:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<child1>
<a />
<b />
<d />
</child1>
<child2>
<c />
<a />
<d />
</child2>
</root>
我尝试过的代码
Xpath 1.0:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<!-- TODO: Auto-generated template -->
<xsl:variable name="ns2" select="/root/child2/child::*"/>
<xsl:copy-of select="/root/child1/child[.=$ns2]"/>
</xsl:template>
</xsl:stylesheet>
Xpath 2.0:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<!-- TODO: Auto-generated template -->
<xsl:variable name="ns1" select="/root/child1/child::*"/>
<xsl:variable name="ns2" select="/root/child2/child::*"/>
<xsl:copy-of select="$ns1 intersect $ns2"/>
</xsl:template>
</xsl:stylesheet>
问题:我得到的结果是空的。
预期结果:
<?xml version="1.0" encoding="UTF-8"?>
<a/>
<d/>
请提出我所缺少的内容。
我尝试了两个不同音符集的set操作交集。我在下面附加了我的代码示例,
答案 0 :(得分:1)
您在这里实际上并不是在进行“交集”,因为child1
的所有子元素都与child2
的子元素不同。仅仅因为两个元素具有相同的名称,就不会使它们成为相同的元素。
看起来像child1
下的元素与child2
下的元素同名的元素
如果您希望XSLT 1.0解决方案获得结果,则需要将xsl:copy-of
更改为此
<xsl:copy-of select="/root/child1/child::*[.=$ns2]"/>
或者这个...
<xsl:copy-of select="/root/child1/*[.=$ns2]"/>
但是,这将返回所有child1
个子元素,因为您正在检查元素的值是否相同,而不是名称。一种方法是...
<xsl:for-each select="/root/child1/*">
<xsl:variable name="name" select="local-name()" />
<xsl:copy-of select=".[$ns2[local-name() = $name]]" />
</xsl:for-each>
或者,如下定义键:
<xsl:key name="child2" match="child2/*" use="local-name()" />
那你就可以做...
<xsl:copy-of select="/root/child1/*[key('child2', local-name())]"/>
在XSLT 2.0中,您可以执行以下操作。...
<xsl:copy-of select="$ns1[some $name in $ns2/local-name() satisfies $name=local-name()]"/>
答案 1 :(得分:0)
不重复蒂姆的正确话,只是针对问题:
XSLT 1.0 (除非使用单个XPath表达式,否则除非使用XSLT标准函数(例如current()
),否则:
<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:template match="child1/*">
<xsl:copy-of select="self::*[../../child2/*[name() = name(current())]]"/>
</xsl:template>
</xsl:stylesheet>
XPath 2.0 :
使用:
/*/child1/*[name() = /*/child2/*/name()]
这可以通过下面的XSLT 2.0转换来验证,该转换评估表达式并输出所选节点:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:sequence select=
"/*/child1/*[name() = /*/child2/*/name()]"/>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<root>
<child1>
<a />
<b />
<d />
</child1>
<child2>
<c />
<a />
<d />
</child2>
</root>
两个转换都能产生想要的正确结果:
<a/>
<d/>