Xslt 基于两个属性值的组合选择唯一节点
我有一些看起来像这样的XML:Xslt 基于两个属性值的组合选择唯一节点,xslt,xpath,Xslt,Xpath,我有一些看起来像这样的XML: <Root> <Documents> <Document id="1"/> </Documents> <People> <Person id="1"/> <Person id="2"/> </People> <Links> <Link personI
<Root>
<Documents>
<Document id="1"/>
</Documents>
<People>
<Person id="1"/>
<Person id="2"/>
</People>
<Links>
<Link personId="1" documentId="1"/>
<Link personId="1" documentId="1"/>
<Link personId="2" documentId="1"/>
</Links>
</Root>
我只想得到“Link”元素,它们具有“personId”和“documentId”的独特组合,因此这两个链接:
<Root>
<Links>
<Link personId="1" documentId="1"/>
<Link personId="2" documentId="1"/>
</Links>
</Root>
我该怎么做呢?我发现,虽然我觉得我的函数稍微复杂一些,可能不适用……我想我需要在某个地方使用key()函数
提前感谢。您可以将多个选择器属性组合到XPath查询中,而不必只是单个属性=值对
您需要使用类似的方法过滤
s,其中current()
函数返回您正在检查唯一性的
s
.[not(preceding-sibling::Link[@personId = current()/@personId and
@documentId = current()/@documentId])]
前面的同级::轴用于查找早期的
元素,方括号中的部分用于检查匹配的ID号。包装整个表达式的not()
表示,只有在前面没有匹配的同级项时,整个括号中的表达式才为真,即前面没有具有相同人员和文档ID的
我的XSLT知识已经过时了,所以我将把这部分留给您。我的想法是,首先查找所有链接,比如说,//Link
,然后在第二步中使用上述XPath过滤它们。我很努力,但想不出任何方法可以一步完成这一切,因为这依赖于current()
函数工作。此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kDocAndPeoById" match="Document|Person" use="@id"/>
<xsl:key name="kLinksByIds" match="Link"
use="concat(@personId,'++',@documentId)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Documents|People|
Link[count(.|key('kLinksByIds',concat(@personId,'++',@documentId))[1])!=1
or not(key('kDocAndPeoById',@personId)/self::Person)
or not(key('kDocAndPeoById',@documentId)/self::Document)]"/>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kLinksByIds" match="Link"
use="concat(@personId,'++',@documentId)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Documents|People|
Link[count(.|key('kLinksByIds',concat(@personId,'++',@documentId))[1])!=1]"/>
</xsl:stylesheet>
输出:
<Root>
<Links>
<Link personId="1" documentId="1"></Link>
<Link personId="2" documentId="1"></Link>
</Links>
</Root>
<Root>
<Links>
<Link personId="1" documentId="1"></Link>
<Link personId="2" documentId="1"></Link>
</Links>
</Root>
如果您不想检查是否存在此类文档或Person@id,则此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kDocAndPeoById" match="Document|Person" use="@id"/>
<xsl:key name="kLinksByIds" match="Link"
use="concat(@personId,'++',@documentId)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Documents|People|
Link[count(.|key('kLinksByIds',concat(@personId,'++',@documentId))[1])!=1
or not(key('kDocAndPeoById',@personId)/self::Person)
or not(key('kDocAndPeoById',@documentId)/self::Document)]"/>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kLinksByIds" match="Link"
use="concat(@personId,'++',@documentId)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Documents|People|
Link[count(.|key('kLinksByIds',concat(@personId,'++',@documentId))[1])!=1]"/>
</xsl:stylesheet>
输出:
<Root>
<Links>
<Link personId="1" documentId="1"></Link>
<Link personId="2" documentId="1"></Link>
</Links>
</Root>
<Root>
<Links>
<Link personId="1" documentId="1"></Link>
<Link personId="2" documentId="1"></Link>
</Links>
</Root>
好的,优雅的。(+1). 我几乎得出了同样的结论。