如何迭代 Nokogiri XML DocumentFragment 中特定名称的子节点?

发布于 2024-12-21 19:26:44 字数 824 浏览 3 评论 0原文

给定一个名为“string”的字符串中的 XML:

<Guide>
  <Master>
    <Part>12345</Part>
    <Sub>
       <Name>A</Name>
    </Sub>
    <Sub>
       <Name>B</Name>
    </Sub>
  </Master>
  <Master>
    <Part>XYZABC</Part>
    <Sub>
       <Name>A</Name>
    </Sub>
    <Sub>
       <Name>C</Name>
    </Sub>
  </Master>
</Guide>

以及这行代码:

bgdoc = Nokogiri::XML::DocumentFragment.parse(xstring.to_xml)

我想循环遍历名为“Part”的所有节点。

我尝试了以下方法:

bgdoc.xpath("//Part").each do |node|

和:

bgdoc.children.each do |node|
  next unless node.name=="Part"

但这没有用。

Given this XML in a string called "string":

<Guide>
  <Master>
    <Part>12345</Part>
    <Sub>
       <Name>A</Name>
    </Sub>
    <Sub>
       <Name>B</Name>
    </Sub>
  </Master>
  <Master>
    <Part>XYZABC</Part>
    <Sub>
       <Name>A</Name>
    </Sub>
    <Sub>
       <Name>C</Name>
    </Sub>
  </Master>
</Guide>

And this line of code:

bgdoc = Nokogiri::XML::DocumentFragment.parse(xstring.to_xml)

I want to loop through all nodes named "Part".

I tried the following:

bgdoc.xpath("//Part").each do |node|

and:

bgdoc.children.each do |node|
  next unless node.name=="Part"

But that didn't work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

居里长安 2024-12-28 19:26:44

问题在于,将 XML 解析为片段会返回部分 XML 文档,即 DocumentFragment,它没有根:

1.9.2-p290 :002 > doc = Nokogiri::XML::DocumentFragment.parse('<a><b>foo</b></a>').root
NoMethodError: undefined method `root' for #<Nokogiri::XML::DocumentFragment:0x00000100b34448>
    from (irb):2
    from /Users/greg/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'

而完整的 XML 文档确实有根:

1.9.2-p290 :003 > doc = Nokogiri::XML('<a><b>foo</b></a>').root
 => #<Nokogiri::XML::Element:0x8058b350 name="a" children=[#<Nokogiri::XML::Element:0x80587b10 name="b" children=[#<Nokogiri::XML::Text:0x80587818 "foo">]>]> 

默认情况下 Nokogiri 是使用像 //Path 这样的 XPath 从文档的根目录进行搜索:

1.9.2-p290 :004 > doc = Nokogiri::XML('<a><Path>foo</Path></a>').search('//Path')
 => [#<Nokogiri::XML::Element:0x8055465c name="Path" children=[#<Nokogiri::XML::Text:0x805543c8 "foo">]>] 

但是由于缺少根目录,片段失败:

1.9.2-p290 :005 > doc = Nokogiri::XML::DocumentFragment.parse('<a><Path>foo</Path></a>').search('//Path')
 => [] 

诀窍是告诉 Nokogiri 在处理片段时要在哪里查找。使用相对搜索或通配符:

1.9.2-p290 :006 > doc = Nokogiri::XML::DocumentFragment.parse('<a><Path>foo</Path></a>').search('.//Path')
 => [#<Nokogiri::XML::Element:0x8053c69c name="Path" children=[#<Nokogiri::XML::Text:0x8053c46c "foo">]>] 

1.9.2-p290 :007 > doc = Nokogiri::XML::DocumentFragment.parse('<a><Path>foo</Path></a>').search('*//Path')
 => [#<Nokogiri::XML::Element:0x8052a208 name="Path" children=[#<Nokogiri::XML::Text:0x80529fec "foo">]>] 

The problem is that parsing the XML as a fragment returns a partial XML document, i.e., a DocumentFragment, which doesn't have a root:

1.9.2-p290 :002 > doc = Nokogiri::XML::DocumentFragment.parse('<a><b>foo</b></a>').root
NoMethodError: undefined method `root' for #<Nokogiri::XML::DocumentFragment:0x00000100b34448>
    from (irb):2
    from /Users/greg/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'

whereas a full XML document does have a root:

1.9.2-p290 :003 > doc = Nokogiri::XML('<a><b>foo</b></a>').root
 => #<Nokogiri::XML::Element:0x8058b350 name="a" children=[#<Nokogiri::XML::Element:0x80587b10 name="b" children=[#<Nokogiri::XML::Text:0x80587818 "foo">]>]> 

By default Nokogiri is going to search from the root of the document with an XPath like //Path:

1.9.2-p290 :004 > doc = Nokogiri::XML('<a><Path>foo</Path></a>').search('//Path')
 => [#<Nokogiri::XML::Element:0x8055465c name="Path" children=[#<Nokogiri::XML::Text:0x805543c8 "foo">]>] 

But that fails with the fragment because of the missing root:

1.9.2-p290 :005 > doc = Nokogiri::XML::DocumentFragment.parse('<a><Path>foo</Path></a>').search('//Path')
 => [] 

The trick is to tell Nokogiri where to look when dealing with the fragment. Using a relative search or a wildcard:

1.9.2-p290 :006 > doc = Nokogiri::XML::DocumentFragment.parse('<a><Path>foo</Path></a>').search('.//Path')
 => [#<Nokogiri::XML::Element:0x8053c69c name="Path" children=[#<Nokogiri::XML::Text:0x8053c46c "foo">]>] 

or

1.9.2-p290 :007 > doc = Nokogiri::XML::DocumentFragment.parse('<a><Path>foo</Path></a>').search('*//Path')
 => [#<Nokogiri::XML::Element:0x8052a208 name="Path" children=[#<Nokogiri::XML::Text:0x80529fec "foo">]>] 
鯉魚旗 2024-12-28 19:26:44
bgdoc = Nokogiri::XML::DocumentFragment.parse(<<EOF)
  <xml stuff>
EOF

bgdoc.xpath(".//Part").each do |node|
  # some instruction
end
bgdoc = Nokogiri::XML::DocumentFragment.parse(<<EOF)
  <xml stuff>
EOF

bgdoc.xpath(".//Part").each do |node|
  # some instruction
end
我乃一代侩神 2024-12-28 19:26:44

如果您只有一个字符串,只需使用 Nokogiri:XML 进行解析即可:

bgdoc = Nokogiri::XML.parse(string)

将为您提供一个根,您可以根据需要使用 xpath //Part

If you do have just a string, simply parsing with Nokogiri:XML instead:

bgdoc = Nokogiri::XML.parse(string)

will give you a root from which you can use the xpath //Part as you expected.

居里长安 2024-12-28 19:26:44
bgdoc.css("Part")

应该做这项工作。

bgdoc.css("Part")

should do the job.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文