您好,我需要帮助解析以下XML。
<xmeml>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
</xmeml>
以下面的
结束<xmeml>
<Doc>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
</xmeml>
我正在尝试创建一个XSLT文档来执行此操作但尚未找到一个有效的文档。 我应该注意,其中所需的匹配参数(在本例中为“abc”)是变量,并且永远不会是静态可搜索实体。
所以在英语中我的XSL会是这样的: 对于包含匹配“单位”值的任何父级 删除除“最后一个”之外的“单位”内包含重复值的所有前面的父项“测试”。
所有帮助最受赞赏 感谢
答案 0 :(得分:2)
您可以使用标识模板复制整个文档,并使用空模板覆盖该模板,以查找要删除的元素。要检查是否应删除<Test>
元素,您可以将其<Unit>
值与后续兄弟元素的值进行比较。
<?xml version="1.0" encoding="UTF-8"?>
<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:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/xmeml/Doc/Test[(Unit = following-sibling::Test/Unit) or (Unit = ../following-sibling::Doc/Test/Unit)][descendant::Unit2[starts-with(.,'1234')]]"/>
</xsl:stylesheet>
由于存在两种<Unit>
值后续值的可能性,因此两种条件都是明确写入的,并在条件中与or
运算符连接。
两种可能性及其各自的XPath条件是:
<Test>
元素中:Unit = following-sibling::Test/Unit
<Test>
元素的后续<Doc>
兄弟中的<Doc>
元素中:Unit = ../following-sibling::Doc/Test/Unit
假设这个输入:
<xmeml>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
</xmeml>
XSLT创建此输出:
<xmeml>
<Doc>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
</xmeml>
答案 1 :(得分:1)
在XSLT 1.0中有两种不同的分组方式 - 简单,使用preceding::
或following::
轴,以及更有效的Muenchian分组方法 - 使用密钥。
以下是效率更高的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="kParentByUnit" match="Test[Unit]" use="Unit"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Test[Unit]">
<xsl:if test=
"generate-id()
=
generate-id(key('kParentByUnit', Unit)[position()=last()])">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<xmeml>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>3456</Unit2>
</Test>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
</xmeml>
产生了想要的正确结果:
<xmeml>
<Doc>
<Test>
<Unit>bcd</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>cde</Unit>
<Unit2>3456</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>def</Unit>
<Unit2>4567</Unit2>
</Test>
</Doc>
<Doc>
<Test>
<Unit>abc</Unit>
<Unit2>1234</Unit2>
</Test>
<Test>
<Unit>efg</Unit>
<Unit2>2345</Unit2>
</Test>
</Doc>
</xmeml>