我正在尝试根据另一个元素子值删除元素。 这是示例 xml 文件:
<Information>
<List>
<Element ID="101278">
<MetaData>
<Value AttributeID="DisplayOrNo">no</Value>
</MetaData>
</Element>
<Element ID="101277">
<MetaData>
<Value AttributeID="DisplayOrNo">yes</Value>
</MetaData>
</Element>
</List>
<Products>
<Product ID="3333">
<Name>test_name</Name>
<Values>
<Value ElementID="101278">test_text</Value>
<Value ElementID="101277">test_text</Value>
</Values>
</Product>
</Products>
</Information>
如果元素列表/元素/元数据/值的值为否,我想删除产品/值中的元素值。 值元素将具有有关元素的 ID 属性的信息。这可能有助于匹配它们。
我期待这样的事情:
<Information>
<List>
<Element ID="101278">
<MetaData>
<Value AttributeID="DisplayOrNo">no</Value>
</MetaData>
</Element>
<Element ID="101277">
<MetaData>
<Value AttributeID="DisplayOrNo">yes</Value>
</MetaData>
</Element>
</List>
<Products>
<Product ID="3333">
<Name>test_name</Name>
<Values>
<Value ElementID="101277">test_text</Value>
</Values>
</Product>
</Products>
</Information>
您认为在匹配和删除 Value 元素之后,还可以完全删除 Information 中的整个 List 吗?或者我是否必须制作第二个 XSLT 才能删除 List ? 应该看起来像这里:
<Information>
<Products>
<Product ID="3333">
<Name>test_name</Name>
<Values>
<Value ElementID="101277">test_text</Value>
</Values>
</Product>
</Products>
</Information>
当前支持的大多数 XSLT 处理器版本都支持 XSLT 3.0(当前版本)或 XSLT 1.0。所以假设你使用例如当前支持 XSLT 2 的 Saxon 版本,它还将支持 XSLT 3 累加器:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy" use-accumulators="display" streamable="yes"/>
<xsl:accumulator name="display" as="xs:string*" initial-value="()" streamable="yes">
<xsl:accumulator-rule match="List/Element[@ID]/MetaData/Value[@AttributeID = 'DisplayOrNo']/text()[. = 'yes']" select="$value, string(ancestor::Element/@ID)"/>
</xsl:accumulator>
<xsl:template match="List"/>
<xsl:template match="Products/Product/Values/Value[not(@ElementID = accumulator-before('display'))]"/>
</xsl:stylesheet>
以下是如何在 XSLT 2.0(甚至 XSLT 1.0)中执行此操作:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="elem-by-id" match="Element[MetaData/Value[@AttributeID='DisplayOrNo']='yes']" use="@ID" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="List"/>
<xsl:template match="Value[not(key('elem-by-id', @ElementID))]"/>
</xsl:stylesheet>