Nokogiri:控制新子元素的元素前缀

时间:2012-02-16 01:36:15

标签: ruby xml namespaces nokogiri prefix

我有一个像这样的xml文档:

<?xml version="1.0" encoding="UTF-8"?>
<foo:root xmlns:foo="http://abc.com#" xmlns:bar="http://def.com" xmlns:ex="http://ex.com">
  <foo:element foo:attribute="attribute_value">
    <bar:otherElement foo:otherAttribute="otherAttributeValue"/>
  </foo:element>
</foo:root>

我需要在元素中添加子元素,使它看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<foo:root xmlns:foo="http://abc.com#" xmlns:bar="http://def.com" xmlns:ex="http://ex.com">
  <foo:element foo:attribute="attribute_value">
    <bar:otherElement foo:otherAttribute="otherAttributeValue"/>
    <bar:otherElement foo:otherAttribute="newAttributeValue"/>
    <ex:yetAnotherElement foo:otherAttribute="yetANewAttributeValue"/>
  </foo:element>
</foo:root>

我可以使用以下内容在正确的位置添加元素:

require 'rubygems'
require 'nokogiri'
doc = Nokogiri::XML::Document.parse(File.open("myfile.xml"))
el = doc.at_xpath('//foo:element')

newEl = Nokogiri::XML::Node.new("otherElement", doc)            
newEl["foo:otherAttribute"] = "newAttributeValue"
el.add_child(newEl)

newEl = Nokogiri::XML::Node.new("yetAnotherElement", doc)           
newEl["foo:otherAttribute"] = "yetANewAttributeValue"
el.add_child(newEl)

然而,新元素的前缀总是“foo”:

<foo:root xmlns:foo="http://abc.com#" xmlns:bar="http://def.com" xmlns:ex="http://ex.com">
  <foo:element foo:attribute="attribute_value">
    <bar:otherElement foo:otherAttribute="otherAttributeValue" /> 
    <foo:otherElement foo:otherAttribute="newAttributeValue" /> 
    <foo:yetAnotherElement foo:otherAttribute="yetANewAttributeValue" /> 
  </foo:element>
</foo:root>

如何在这些新子元素的元素名称上设置前缀?谢谢, 锐衡

2 个答案:

答案 0 :(得分:3)

(删除了关于定义命名空间的位,与问题正交并在编辑中修复)

只需在代码中添加几行,即可获得所需的结果:

require 'rubygems'
require 'nokogiri'
doc = Nokogiri::XML::Document.parse(File.open("myfile.xml"))
el = doc.at_xpath('//foo:element')

newEl = Nokogiri::XML::Node.new("otherElement", doc)            
newEl["foo:otherAttribute"] = "newAttributeValue"
# ADDITIONAL CODE
newEl.namespace = doc.root.namespace_definitions.find{|ns| ns.prefix=="bar"}
#
el.add_child(newEl)

newEl = Nokogiri::XML::Node.new("yetAnotherElement", doc)           
newEl["foo:otherAttribute"] = "yetANewAttributeValue"
# ADDITIONAL CODE
newEl.namespace = doc.root.namespace_definitions.find{|ns| ns.prefix == "ex"}
#
el.add_child(newEl)

结果:

<?xml version="1.0" encoding="UTF-8"?>
<foo:root xmlns:abc="http://abc.com#" xmlns:def="http://def.com" xmlns:ex="http://ex.com" xmlns:foo="http://foo.com" xmlns:bar="http://bar.com">
  <foo:element foo:attribute="attribute_value">
    <bar:otherElement foo:otherAttribute="otherAttributeValue"/>
    <bar:otherElement foo:otherAttribute="newAttributeValue"/>
    <ex:yetAnotherElement foo:otherAttribute="yetANewAttributeValue"/>
  </foo:element>
</foo:root>

答案 1 :(得分:1)

未定义名称空间“foo”。

有关详细信息,请参阅此处: Nokogiri/Xpath namespace query