如何使用 Nokogiri 在 NodeSet 中添加子节点 [英] How to add child nodes in NodeSet using Nokogiri
问题描述
我正在尝试在根节点下添加子节点.我使用以下 XML 进行了尝试,但它不起作用.
I am trying to add child nodes under a root node. I tried it with the following XML but it doesn't work.
builder = Nokogiri::XML::Builder.with(@doc) do |xml|
nodes = Nokogiri::XML::NodeSet.new(@doc, [])
[].each {|nodes_one_by_one|
<< nodes_one_by_one.Book
<< nodes_one_by_one.Pen
}
end
我需要像这样在根节点下添加节点:
I need to add nodes below a root node like this:
<Catalog>
<Book>abc</Book>
<Book_Author>Benjamin</Book_author>
</Catalog>
这对我有用,但我要在文档中的特定位置之后添加这些节点:
That works for me, but I to add these Nodes after a specific position in the document:
<Catalog>
<!--
<Book>abc</Book>
<Book_Author>Benjamin</Book_author>
-->
<Interface></Interface>
<Dialog></Dialog>
<Manifest></Manifest>
</Catalog>
我用 at_xpath('//Catlog')
尝试过,但它把它添加到元素的末尾:
I tried it with at_xpath('//Catlog')
but it is adding it at the end of the element:
<Catalog>
<Interface></Interface>
<Dialog></Dialog>
<Manifest></Manifest>
<!--
<Book>abc</Book>
<Book_Author>Benjamin</Book_author>
-->
</Catalog>
和
book = Nokogiri::XML::Node.new('book', doc)
pen = Nokogiri::XML::Node.new('pen', doc)
.
.
有没有办法使用 each
来循环而不是一个一个地添加它们.我试过这种方式,但这不起作用:
Is there a way to loop using each
instead of adding them one by one. I tried this way but that doesn't work:
builder = Nokogiri::XML::Builder.with(doc) do |xml|
nodes = Nokogiri::XML::Node.new(doc, [])
[].each {|child_list_element|
child_list_element.Book "value"
child_list_element.Pen "value"
child_list_element.Diary "value"
child_list_element.Pen_stand "value"
child_list_element.Pencil "value"
.
.
.
}
end
doc << nodes
代码可能有误,但我想这样做.
The code might be wrong, but I want to do this way.
另外,我可以将所有元素添加为 NodeSet 而不是 Node.
Also, can I add all the elements as a NodeSet instead of a Node.
嵌套的 OpenStruct 似乎不起作用.我试过了:
Nested OpenStruct doesn't seem to be working. I tried:
Store 目录集:
require 'ostruct'
require 'nokogiri'
collection = [
OpenStruct.new(:catalogStoreNumber => '657758',
:catalogStoreId => 'CTH6536',
:catalogStoreLocation => 'UnitedStates',
:catalogOwnerId => 'TYCT11190',
:catalogOwner => 'McGrawHill Pub.',
:catalogList => OpenStruct.new(
:catalogProductInfo => OpenStruct.new(
:productType => 'Book',
:productName => 'The Client',
:productId => 'CRSUS113246A',
:productCategory => 'Crime And Suspense',
:productSubcategory => 'Vintage Books',
:productPrice => '45.50 USD',
:productAuthor => OpenStruct.new(
:authorFirstName =>'John Grisham',
:authorMiddleName=> 'Willburt',
:authorContact => '19876648981')),
:catalogProductInfo => OpenStruct.new(
:productType => 'Pen',
:productName => 'Reynolds',
:productId => 'PRREY546647',
:productCategory => 'Misc. Stationary',
:productSubcategory => 'Stationery Items',
:productPrice => '3.00 USD',
:productManufacturer => 'Reynolds Inc.',
:productAuthor => OpenStruct.new(
:authorFirstName => 'Ryan Reynolds',
:authorMiddleName => 'William',
:authorContact => '16577589898')),
:catalogListType => 'ProductCollection',
:catalogListSource => 'Web'
),
:catalogVerificaitionLog => OpenStruct.new(
:catalogVerificationStatus => 'Verified',
:catalogVerificationDateTime => '2012-03-12T13:00:15+5:30',
:catalogVerificationId => '64774A',
:catalogVerificationRequestedBy => 'user_121')
)]
我想访问第一个 catalogProductInfo
的 productType
并且我使用了
I want to access the productType
of the first catalogProductInfo
and I used
collection.catalogList.catalogProductInfo.productType.content
我收到了这个错误:
undefined method `productType' for #<Array:0x3057438> (NoMethodError)
OpenStruct 是否支持嵌套的 OpenStruct 我想使用 OpenStruct 和 Nokogiri 构造以下格式的 XML?
Does OpenStruct have the support for the nested OpenStruct I want to construct XML in the following format using OpenStruct and Nokogiri?
<CatalogOrder>
<CatalogStoreNumber>657758</CatalogStoreNumber>
<CatalogStoreId>CTH6536</CatalogStoreId>
<CatalogStoreLocation>UnitedStates</CatalogStoreLocation>
<CatalogOwnerId>TYCT11190</CatalogOwnerId>
<CatalogOwner>McGrawHill Pub.</CatalogOwner>
<CatalogList>
<CatalogProductInfo>
<ProductType>Book</ProductType>
<ProductName>The Client</ProductName>
<ProductId>CRSUS113246A</ProductId>
<ProductCategory>Crime And Suspense</ProductCategory>
<ProductSubCategory>Vintage Books</ProductSubCategory>
<ProductPrice>45.50 USD</ProductPrice>
<ProductAuthor>
<AuthorFirstName>John Grisham</AuthorFirstName>
<AuthorMiddleName>Willbur</AuthorMiddleName>
<AuthorContact>19876648981</AuthorContact>
</ProductAuthor>
</CatalogProductInfo>
<CatalogProductInfo>
<ProductType>Pen</ProductType>
<ProductName>Reynolds</ProductName>
<ProductId>PRREY546647</ProductId>
<ProductCategory>Misc. Stationary</ProductCategory>
<ProductSubCategory>Stationary Items</ProductSubCategory>
<ProductPrice>3.00 USD</ProductPrice>
<ProductAuthor>
<AuthorFirstName>Ryan Reynolds</AuthorFirstName>
<AuthorMiddleName>William</AuthorMiddleName>
<AuthorContact>16577589898</AuthorContact>
</ProductAuthor>
</CatalogProductInfo>
<CatalogListType>ProductCollection</CatalogListType>
<CatalogListSource>Web</CatalogListSource>
</CatalogList>
<CatalogVerificationLog>
<CatalogVerificationStatus>Verified</CatalogVerificationStatus>
<CatalogVerificationDateTime>2012-03-12T13:00:15+5:30</CatalogVerificationDateTime>
<CatalogVerificationId>64774A</CatalogVerificationId>
<CatalogVerificationRequestedBy>User_121</CatalogVerificationRequestedBy>
</CatalogVerificationLog>
</CatalogOrder>
我想使用 Nokogiri 和 OpenStruct 来做到这一点,但我不确定 OpenStruct 是否可行,因为它缺乏嵌套功能.有没有其他方法可以使用 JSON 来实现这一点而没有任何限制?
I want to do this using Nokogiri and OpenStruct, but I am not sure whether it is possible with OpenStruct, as it lacks nesting capabilities. Is there any other way to use JSON to accomplish this without any limitations?
推荐答案
如果我没理解错的话,以下应该是你要找的大致内容:
If I am understanding you correctly, the following should be roughly what you are looking for:
doc = Nokogiri::XML(original_xml_string)
catalog = doc.at_css('Catalog') # #at_css will just grab the first node.
# use #css if you want to loop through several.
# alternatively just use doc.root
book = Nokogiri::XML::Node.new('Book', doc)
book_author = Nokogiri::XML::Node.new('Book_Author', doc)
book.content = 'abc'
book_author.content = 'benjamin'
catalog << book
catalog << book_author
<<
应该在元素结束之前附加节点.
The <<
should append the nodes just before the end of the element.
在更新问题并使用@Phrogz 的建议进行简化后,这应该满足您的要求:
After the updated question and simplified with @Phrogz's suggestions, this should meet your requirements:
require 'nokogiri'
xml = <<'XML'
<Catalog>
<Interface></Interface>
<Dialog></Dialog>
<Manifest></Manifest>
</Catalog>
XML
doc = Nokogiri::XML(xml)
catalog = doc.root
catalog.first_element_child.before("<Book_Author>abc</Book_Author>")
catalog.first_element_child.before("<Book>benjamin</Book>")
puts doc.to_xml
要遍历集合,动态添加节点,并使用 NodeSet,请尝试以下操作:
To iterate over a collection, add the nodes dynamically, and using a NodeSet, try the following:
require 'nokogiri'
require 'ostruct'
xml = <<-'XML'
<Catalog>
<Interface></Interface>
<Dialog></Dialog>
<Manifest></Manifest>
</Catalog>
XML
collection = [
OpenStruct.new(book: '1984', pen: 'George Orwell'),
OpenStruct.new(book: 'Thinking, Fash and Slow', pen: 'Daniel Kahneman')
]
doc = Nokogiri::XML(xml)
catalog = doc.root
node_set = Nokogiri::XML::NodeSet.new(doc)
collection.each do |object|
book = Nokogiri::XML::Node.new('Book', doc)
book_author = Nokogiri::XML::Node.new('Book_Author', doc)
book.content = object.book
book_author.content = object.pen
node_set << book
node_set << book_author
end
catalog.first_element_child.before(node_set)
puts doc.to_xml
这篇关于如何使用 Nokogiri 在 NodeSet 中添加子节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!