我有一个XML,我想用xslt转换它。 输入看起来像这样。
<xmeml>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>tuvw</Unit3>
</Test>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>uvwx</Unit3>
</Test>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
</xmeml>
输出应该如下所示。
<xmeml>
<Doc>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
</xmeml>
我想要删除符合以下条件的任何Test节点。 - Unit3子节点以tuv或uvw启动。 - AND单元和单元2值都在另一个测试节点中重复/重复发生
提前感谢您的帮助。
答案 0 :(得分:1)
此转换(基于Muenchian分组):
<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="kTest"
match="Test[starts-with(Unit3, 'tuv') or starts-with(Unit3, 'uvw')]"
use="concat(Unit, '+', Unit2)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"Test[starts-with(Unit3, 'tuv') or starts-with(Unit3, 'uvw')]
[not(generate-id()
=
generate-id(key('kTest', concat(Unit, '+', Unit2))[last()]))]"/>
</xsl:stylesheet>
应用于提供的XML文档:
<xmeml>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>tuvw</Unit3>
</Test>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>uvwx</Unit3>
</Test>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
</xmeml>
生成正确的结果(实现所有要求):
<xmeml>
<Doc>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>uvwx</Unit3>
</Test>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
</xmeml>
<强>更新强>:
OP对这个问题有自己的解释,这个问题含糊不清,而且没有精确定义。
经过相当多的猜测,这可能是他想要的......:
<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="kTest"
match="Test" use="concat(Unit, '+', Unit2)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"Test[starts-with(Unit3, 'tuv') or starts-with(Unit3, 'uvw')]
[not(generate-id()
=
generate-id(key('kTest', concat(Unit, '+', Unit2))
[not(position()=1)])
)]"/>
</xsl:stylesheet>
当在提供的XML文档(上面)上应用此转换时,现在结果与OP认为的想要结果相同:
<xmeml>
<Doc>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
<Unit3>wxyz</Unit3>
</Test>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
<Doc>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
<Unit3>wxyz</Unit3>
</Test>
</Doc>
</xmeml>
答案 1 :(得分:1)
Dimitre解决方案的这个调整怎么样......
<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="kTest" match="Test" use="concat(Unit, '+', Unit2)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"Test[key('kTest', concat(Unit, '+', Unit2))[2]]
[starts-with(Unit3, 'tuv') or starts-with(Unit3, 'uvw')]"/>
</xsl:stylesheet>
据我所知,转型规则是:
2.1文档中存在另一个Test节点(称为Test(other)),以便:
(Test(reference) / Unit = Test(other) / Unit) AND
(Test(reference) / Unit2 = Test(other) / Unit2)
2.2参考测试节点的Unit3子节点以tuv或uvw
开头此输出与发布的OP完全相同。有趣的是,如果我正确地理解了这个问题,Dimitre最近刚刚提供了解决方案,解决了与此问题相同的问题XSL comparison of nodes。同样,如果我正确理解了您的问题,标题会产生误导。 “去除重复”通常被认为意味着重复数据删除,如(1,2,2,3) - >中所述。 (1,2,3);而你想要的,如(1,2,2,3) - &gt; (1,3)通常被描述为“选择唯一节点/值”。