将元素插入 XML 片段时出现问题
Problems inserting elements into XML fragment
基本问题实际上非常简单:我无法使 Nokogiri DocumentFragment 的行为符合预期。它有两个节点,而不是如果它是一个实际文档时应该有的节点,并且它不将该节点识别为一个元素,而文档识别为一个元素。
我需要片段而不是文档,因为我想将生成的 XML 作为元素插入到另一个文档(或片段)中。看来我可能使用了错误的片段方法。
我正在尝试在 Rails 应用程序的 Ruby 中使用一种名为 build_xml 的方法为对象构建 XML 表示。因为我有一个嵌套对象的层次结构,所以我将它作为一个通用方法,将在 class 之间共享,并在每个 class 中使用一个 class 常量来处理 class-具体信息。每个对象都会创建一个 Nokogiri DocumentFragment 而不是完整的文档,因此任何返回的 XML 字符串都可以作为元素插入到包含对象的 XML 中。
我的问题是我无法获取显示其元素的片段。所以,我有:
xml_string = self.to_xml({skip_types:true, skip_instruct: true}) # Use default to_xml method to get started
xml_fragment = Nokogiri::XML::DocumentFragment.parse(xml_string) # Create Nokogiri doc fragment
此时,我想遍历每个嵌套对象并将其添加为片段唯一元素的子元素。但是,片段的 element_children() 方法 returns 是一个空数组,而它的 children() 方法 returns 是两个项目的数组,第一个是我想要的元素,第二个第二个是一些文本对象,只包含一个换行符。
示例:
df = Datafile.first
xml_string = df.to_xml({skip_types:true, skip_instruct: true})
frag = Nokogiri::XML::DocumentFragment.parse(xml_string)
frag.element_children # => returns []
frag.children # => returns array of two children, one of which is datafile element, the other of which is just a linefeed.
如果我创建一个实际的 XML 文档而不只是一个片段,那么该文档会按预期填充 element_children,此外,doc.children 只有一个元素,没有第二个多余的节点。我可以尝试处理文档,然后在返回之前将其转换为片段,但我不知道生成的片段是否仍然存在问题,我更愿意了解发生了什么,所以我可以相反,只要做对就行了。
所以...
- 为什么片段不将其唯一的真实节点识别为元素?有什么我应该做的来强迫这个吗? Nokogiri 文档对元素节点的描述不多,但看起来它们没有可访问的属性来将它们与通用节点区分开来。
- 为什么在我解析片段时会出现第二个空节点?
- 我是否只需要查看完整的文件?有没有一种简单的方法可以将文档转换为片段?
- 我应该完全以其他方式来做这件事吗?
您将整个 XML 字符串传递给 parse
,只需要 the tags as an argument.
根据 their docs,你应该这样做:
xml_fragment = Nokogiri::XML.fragment(xml_string)
不确定这是否真的是导致问题的原因,但这可能是一个开始的地方。
虽然问题不明确,但这个关于插入和删除节点的小概述也许会有所帮助:
require 'nokogiri'
inserted_text = 'hello world!'
这将解析片段:
doc = Nokogiri::XML::DocumentFragment.parse('<foo><bar></bar></foo>')
doc.to_xml # => "<foo>\n <bar/>\n</foo>"
将其与完整解析进行比较,后者添加了 XML 声明:
doc = Nokogiri::XML('<foo><bar></bar></foo>')
doc.to_xml # => "<?xml version=\"1.0\"?>\n<foo>\n <bar/>\n</foo>\n"
找到<bar>
节点并添加子节点:
bar = doc.at('bar')
bar.children = "<baz a='1'>#{ inserted_text }</baz>"
doc.to_xml # => "<foo>\n <bar>\n <baz a=\"1\">hello world!</baz>\n </bar>\n</foo>"
我正在使用 at
方法,它会找到第一个匹配的节点。它比 search
更具体 returns 所有匹配的节点作为一个节点集,类似于节点数组。这两种方法都采用 CSS 或 XPath 选择器; CSS 通常更容易阅读,但 XPath 有更多的功能,所以首先根据易读性在它们之间进行选择,然后是功能。 Nokogiri 非常乐意在同一个脚本中同时使用这两种方法。 at
和 search
有 CSS/XPath 个特定的等价物:分别为 at_css
、at_xpath
和 css
和 xpath
。 at('some_selector')
等同于 search('some_selector').first
.
此外,请注意 Nokogiri 很乐意接受包含您要添加的 XML 或 HTML 的字符串。它会将其解析成片段,让您更轻松地定义您要使用的内容。
这是轻松删除节点的方法:
baz = doc.at('baz').remove
要更改节点的属性:
baz['a'] = 'hiya!'
并将节点移动到其他地方:
doc.at('foo').add_child(baz)
这让我们将节点视为 XML:
doc.to_xml # => "<foo>\n <bar/>\n <baz a=\"hiya!\">hello world!</baz>\n</foo>"
这让我们可以像查看文件一样查看 XML:
puts doc.to_xml
# >> <foo>
# >> <bar/>
# >> <baz a="hiya!">hello world!</baz>
# >> </foo>
好吧,解决办法就是更新 Nokogiri 的版本。据推测,这是在版本 1.6.3.1 和 1.6.6.2 之间修复的错误。
基本问题实际上非常简单:我无法使 Nokogiri DocumentFragment 的行为符合预期。它有两个节点,而不是如果它是一个实际文档时应该有的节点,并且它不将该节点识别为一个元素,而文档识别为一个元素。
我需要片段而不是文档,因为我想将生成的 XML 作为元素插入到另一个文档(或片段)中。看来我可能使用了错误的片段方法。
我正在尝试在 Rails 应用程序的 Ruby 中使用一种名为 build_xml 的方法为对象构建 XML 表示。因为我有一个嵌套对象的层次结构,所以我将它作为一个通用方法,将在 class 之间共享,并在每个 class 中使用一个 class 常量来处理 class-具体信息。每个对象都会创建一个 Nokogiri DocumentFragment 而不是完整的文档,因此任何返回的 XML 字符串都可以作为元素插入到包含对象的 XML 中。
我的问题是我无法获取显示其元素的片段。所以,我有:
xml_string = self.to_xml({skip_types:true, skip_instruct: true}) # Use default to_xml method to get started
xml_fragment = Nokogiri::XML::DocumentFragment.parse(xml_string) # Create Nokogiri doc fragment
此时,我想遍历每个嵌套对象并将其添加为片段唯一元素的子元素。但是,片段的 element_children() 方法 returns 是一个空数组,而它的 children() 方法 returns 是两个项目的数组,第一个是我想要的元素,第二个第二个是一些文本对象,只包含一个换行符。
示例:
df = Datafile.first
xml_string = df.to_xml({skip_types:true, skip_instruct: true})
frag = Nokogiri::XML::DocumentFragment.parse(xml_string)
frag.element_children # => returns []
frag.children # => returns array of two children, one of which is datafile element, the other of which is just a linefeed.
如果我创建一个实际的 XML 文档而不只是一个片段,那么该文档会按预期填充 element_children,此外,doc.children 只有一个元素,没有第二个多余的节点。我可以尝试处理文档,然后在返回之前将其转换为片段,但我不知道生成的片段是否仍然存在问题,我更愿意了解发生了什么,所以我可以相反,只要做对就行了。
所以...
- 为什么片段不将其唯一的真实节点识别为元素?有什么我应该做的来强迫这个吗? Nokogiri 文档对元素节点的描述不多,但看起来它们没有可访问的属性来将它们与通用节点区分开来。
- 为什么在我解析片段时会出现第二个空节点?
- 我是否只需要查看完整的文件?有没有一种简单的方法可以将文档转换为片段?
- 我应该完全以其他方式来做这件事吗?
您将整个 XML 字符串传递给 parse
,只需要 the tags as an argument.
根据 their docs,你应该这样做:
xml_fragment = Nokogiri::XML.fragment(xml_string)
不确定这是否真的是导致问题的原因,但这可能是一个开始的地方。
虽然问题不明确,但这个关于插入和删除节点的小概述也许会有所帮助:
require 'nokogiri'
inserted_text = 'hello world!'
这将解析片段:
doc = Nokogiri::XML::DocumentFragment.parse('<foo><bar></bar></foo>')
doc.to_xml # => "<foo>\n <bar/>\n</foo>"
将其与完整解析进行比较,后者添加了 XML 声明:
doc = Nokogiri::XML('<foo><bar></bar></foo>')
doc.to_xml # => "<?xml version=\"1.0\"?>\n<foo>\n <bar/>\n</foo>\n"
找到<bar>
节点并添加子节点:
bar = doc.at('bar')
bar.children = "<baz a='1'>#{ inserted_text }</baz>"
doc.to_xml # => "<foo>\n <bar>\n <baz a=\"1\">hello world!</baz>\n </bar>\n</foo>"
我正在使用 at
方法,它会找到第一个匹配的节点。它比 search
更具体 returns 所有匹配的节点作为一个节点集,类似于节点数组。这两种方法都采用 CSS 或 XPath 选择器; CSS 通常更容易阅读,但 XPath 有更多的功能,所以首先根据易读性在它们之间进行选择,然后是功能。 Nokogiri 非常乐意在同一个脚本中同时使用这两种方法。 at
和 search
有 CSS/XPath 个特定的等价物:分别为 at_css
、at_xpath
和 css
和 xpath
。 at('some_selector')
等同于 search('some_selector').first
.
此外,请注意 Nokogiri 很乐意接受包含您要添加的 XML 或 HTML 的字符串。它会将其解析成片段,让您更轻松地定义您要使用的内容。
这是轻松删除节点的方法:
baz = doc.at('baz').remove
要更改节点的属性:
baz['a'] = 'hiya!'
并将节点移动到其他地方:
doc.at('foo').add_child(baz)
这让我们将节点视为 XML:
doc.to_xml # => "<foo>\n <bar/>\n <baz a=\"hiya!\">hello world!</baz>\n</foo>"
这让我们可以像查看文件一样查看 XML:
puts doc.to_xml
# >> <foo>
# >> <bar/>
# >> <baz a="hiya!">hello world!</baz>
# >> </foo>
好吧,解决办法就是更新 Nokogiri 的版本。据推测,这是在版本 1.6.3.1 和 1.6.6.2 之间修复的错误。