如何使用 Nokogiri 在 NodeSet 中添加子节点 [英] How to add child nodes in NodeSet using Nokogiri

查看:53
本文介绍了如何使用 Nokogiri 在 NodeSet 中添加子节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在根节点下添加子节点.我使用以下 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')
    )]

我想访问第一个 catalogProductInfoproductType 并且我使用了

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆