我有一些看起来像这样的XML:
<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>
我感兴趣的是只获得具有'personId'和'documentId'的独特组合的'Link'元素,所以这两个链接:
<Root>
<Links>
<Link personId="1" documentId="1"/>
<Link personId="2" documentId="1"/>
</Links>
</Root>
我怎么可能这样做?我找到了this question,虽然我觉得我的情况稍微复杂一些但可能不适用......我估计我需要在某个地方使用key()函数...
提前致谢。
答案 0 :(得分:3)
此样式表:
<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>
输出:
<Root>
<Links>
<Link personId="1" documentId="1"></Link>
<Link personId="2" documentId="1"></Link>
</Links>
</Root>
如果你没有兴趣检查是否有这样的Document或Person @id,那么这个样式表:
<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>
答案 1 :(得分:1)
您可以将多个选择器属性组合到XPath查询中,而不必只是一个attribute = value对。
答案 2 :(得分:0)
您需要使用类似的内容过滤<Link>
,其中current()
函数返回<Link>
您要检查的唯一性。
.[not(preceding-sibling::Link[@personId = current()/@personId and
@documentId = current()/@documentId])]
preceding-sibling::
轴用于查找较早的<Link>
元素,方括号中的部分用于检查匹配的ID号。包裹整个表达式的not()
表示只有当前面的兄弟匹配没有匹配时,整个括号表达式才为真,即没有先前的<Link>
具有相同的人和文档ID。
我的XSLT知识生疏了,所以我会把那部分留给你。我在想的是你首先找到所有链接,比如//Link
,然后在上面的XPath的第二步中过滤它们。我努力了,但想不出任何办法一步到位,因为这依赖于current()
功能。