ruby - 搜索 XML 并将节点的子集作为 XML 获取

标签 ruby xml search xpath nokogiri

给定一个搜索词,如何在 XML 中搜索节点的属性并返回仅包含与该词匹配的节点及其父节点的 XML,一直追踪到根节点。

这是输入 XML 的示例:

<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>

我正在寻找搜索词“角度”的输出:

<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 的 XPath 是 "//*[contains(@name,'angles')]"

我在 Ruby 中使用 Nokogiri 来搜索 XML,它为我提供了一个包含与该术语匹配的所有节点的节点集。我不知道如何从那组节点构造回 XML。

谢谢!

编辑:修复了示例应该是 .谢谢迪米特雷。

编辑 2:再次修复 xml 以确保格式正确。

最佳答案

首先,请注意所提供的所需输出是不正确的,并且以下元素在文档后面没有结束标记:

<node name = "C">

XPath 表达式的计算结果可以是 XML 文档中的一组节点,但这些注释不能被 XPath 更改

这个 XPath 表达式选择了

nodes that match the term along with their parents all the way tracing to the root node

//*[contains(@name,'angles') and not(node())]/ancestor::*

然而,节点并没有改变,它们包含了它们所有的 child ,这意味着以 Root 为根的完整子树在返回结果中仍然是 Root 的子树.

如果您想要获得与原始 XML 文档具有不同结构的新文档(节点集),您必须使用另一种承载 XPath 的语言。有许多这样的语言,例如 XSLT、XQuery 和任何具有 XML DOM 实现的语言。

这是一个 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>

当此转换应用于提供的 XML 文档时(更正为格式正确):

<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>

关于ruby - 搜索 XML 并将节点的子集作为 XML 获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3273254/

相关文章:

java - Java 中的方法不返回任何内容

ruby-on-rails - SimpleForm 删除包装 div

ruby - 如何在 Ruby Net :HTTP? 中处理多部分 http 响应

ruby-on-rails - TCP 套接字 IO 卡住

android - 嵌套 LinearLayout 内 ImageView 中心的图像

xml - 为什么这个针对子文本内容的 XPath 测试会失败?

ruby - 如何向 CSV 文件添加列?

javascript - 使用 Javascript 生成 BPMN XML

google-app-engine - 在数据存储实体中搜索的最佳方式是什么?

使用多个关键字的 Jquery Grep 和 Map Json