我有以下 XML,我试图根据名称子节点获取唯一节点。
原始 XML:
<products>
<product>
<name>White Socks</name>
<price>2.00</price>
</product>
<product>
<name>White Socks/name>
<price>2.00</price>
</product>
<product>
<name>Blue Socks</name>
<price>3.00</price>
</product>
</products>
我想要得到的:
<products>
<product>
<name>White Socks</name>
<price>2.00</price>
</product>
<product>
<name>Blue Socks</name>
<price>3.00</price>
</product>
</products>
我已经尝试过各种方法但不值得在这里列出,我得到的最接近的是使用 XPath 但它只返回如下所示的名称。但是,这是错误的,因为我想要上面的完整 XML,而不仅仅是节点值。
White Socks
Blue Socks
我正在使用 Ruby 并尝试像这样遍历节点:
@doc.xpath("//product").each do |node|
显然上面的当前获取所有产品节点,而我想要所有唯一产品节点(使用子节点“名称”作为唯一标识符)
最佳答案
这个转换:
<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="kProdByName" match="product"
use="name"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"product
[not(generate-id()
=
generate-id(key('kProdByName',name)[1])
)
]"/>
</xsl:stylesheet>
应用于提供的 XML 文档时(更正为格式正确):
<products>
<product>
<name>White Socks</name>
<price>2.00</price>
</product>
<product>
<name>White Socks</name>
<price>2.00</price>
</product>
<product>
<name>Blue Socks</name>
<price>3.00</price>
</product>
</products>
产生想要的、正确的结果:
<products>
<product>
<name>White Socks</name>
<price>2.00</price>
</product>
<product>
<name>Blue Socks</name>
<price>3.00</price>
</product>
</products>
请注意:
identity rule “按原样”复制每个节点。
有一个单独的覆盖模板,用于排除任何不是其组中第一个的
product
元素。
XPath-one-liner(请注意这是 O(N^2) —— 在许多 product
元素上会非常慢) :
/*/product[not(name = following-sibling::product/name)]
关于ruby - 如何使用 Ruby 选择唯一的 XML 节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5019344/