Ruby 搜索XML并获取作为XML的节点子集
给定一个搜索词,如何搜索XML中节点的属性并返回XML,该XML只包含与该词匹配的节点及其父节点,一直跟踪到根节点 以下是输入XML的示例:Ruby 搜索XML并获取作为XML的节点子集,ruby,xml,search,xpath,nokogiri,Ruby,Xml,Search,Xpath,Nokogiri,给定一个搜索词,如何搜索XML中节点的属性并返回XML,该XML只包含与该词匹配的节点及其父节点,一直跟踪到根节点 以下是输入XML的示例: <root> <node name = "Amaths"> <node name = "Bangles"/> </node> <node name = "C"> <node name = "Dangles"> <node name =
<root>
<node name = "Amaths">
<node name = "Bangles"/>
</node>
<node name = "C">
<node name = "Dangles">
<node name = "E">
<node name = "Fangles"/>
</node>
</node>
<node name = "Gdecimals" />
</node>
<node name = "Hnumbers"/>
<node name = "Iangles"/>
</root>
我正在寻找搜索词“角度”的输出:
我用来搜索xml的XPath是“/*[contains(@name,'angles')]”“
我在Ruby中使用Nokogiri来搜索XML,它为我提供了一个匹配该术语的所有节点的节点集。我不知道如何从这组节点构造回XML
谢谢
编辑:修复了该示例应已修复的问题。谢谢你,迪米特
编辑2:再次修复xml格式是否正确。首先,请注意显示的所需输出不正确,并且以下元素在文档后面没有结束标记:
<node name = "C">
但是,节点不会更改,并且它们包含所有子节点,这意味着根在Root
中的完整子树仍然是返回结果中Root
的子树
如果您想要获得与原始XML文档结构不同的新文档(节点集),则必须使用承载XPath的另一种语言。有许多这样的语言,如XSLT、XQuery和任何带有XMLDOM实现的语言
这里是一个XSLT转换,生成所需的结果:
<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:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(descendant-or-self::*[contains(@name, 'angles')])]"/>
</xsl:stylesheet>
<root>
<node name = "Amaths">
<node name = "Bangles"/>
</node>
<node name = "C">
<node name = "Dangles">
<node name = "E">
<node name = "Fangles"/>
</node>
<node name = "Gdecimals" />
</node>
</node>
<node name = "Hnumbers"/>
<node name = "Iangles"/>
</root>
<root>
<node name="Amaths">
<node name="Bangles"/>
</node>
<node name="C">
<node name="Dangles">
<node name="E">
<node name="Fangles"/>
</node>
</node>
</node>
<node name="Iangles"/>
</root>
在提供的XML文档上应用此转换时(更正为格式正确):
<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:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(descendant-or-self::*[contains(@name, 'angles')])]"/>
</xsl:stylesheet>
<root>
<node name = "Amaths">
<node name = "Bangles"/>
</node>
<node name = "C">
<node name = "Dangles">
<node name = "E">
<node name = "Fangles"/>
</node>
<node name = "Gdecimals" />
</node>
</node>
<node name = "Hnumbers"/>
<node name = "Iangles"/>
</root>
<root>
<node name="Amaths">
<node name="Bangles"/>
</node>
<node name="C">
<node name="Dangles">
<node name="E">
<node name="Fangles"/>
</node>
</node>
</node>
<node name="Iangles"/>
</root>
生成所需(正确)结果:
<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:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(descendant-or-self::*[contains(@name, 'angles')])]"/>
</xsl:stylesheet>
<root>
<node name = "Amaths">
<node name = "Bangles"/>
</node>
<node name = "C">
<node name = "Dangles">
<node name = "E">
<node name = "Fangles"/>
</node>
<node name = "Gdecimals" />
</node>
</node>
<node name = "Hnumbers"/>
<node name = "Iangles"/>
</root>
<root>
<node name="Amaths">
<node name="Bangles"/>
</node>
<node name="C">
<node name="Dangles">
<node name="E">
<node name="Fangles"/>
</node>
</node>
</node>
<node name="Iangles"/>
</root>
好问题(+1)。有关解释和简单的XSLT解决方案,请参见我的答案。@Dimitre:非常感谢!关于输出中的错误,我已经解决了这个问题。将尝试您的解决方案并让您知道。再次感谢。@Vijay Dev:XML文档的格式仍然不正确。我已更改了答案,以包含您最新的XML文档(已更正为格式正确)和新结果。@Dimitre:您介意回答一个变体吗?我需要在输出xml中包含与搜索词匹配的节点的所有子节点,不管它们的“name”属性是什么。如何修改XPath以实现这一点?谢谢@Vijay Dev:如果我理解的很好,这是我回答中的第一个XPath表达式。编写了另一个xsl:template来匹配“*[(祖先或自我::*[contains(@name,\'angles\'))]”似乎可以正常工作。如果有更好的办法,请告诉我。