将属性添加到现有XML文件中的xml标记

时间:2012-01-18 12:27:12

标签: ruby xml nokogiri xml-namespaces

我正在解析docx文件并收到错误:“未定义的名称空间前缀”。为了解决这个问题,我决定定义名称空间,它在根标记中不存在。

要做到这一点,我需要在根标记中插入带有“(url)”值的“xmlns:wp”属性。

如何使用Nokogiri宝石做到这一点?

或者如果使用其他宝石更容易,请告诉我如何。我正在使用以下代码将属性添加到XML元素:

doc = Nokogiri::XML(File.open(path_to_file)
doc.xpath('w:document').each do |document|
  document.set_attribute('xmlns:wp', 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing')
end

并使用添加的属性获取新元素。然后我可以重写整个文件,但也许有另一种方法来解决我的问题?

1 个答案:

答案 0 :(得分:1)

您需要提供有关导致该错误的操作的更多详细信息。只是解析一个XML文档就不会让Nokogiri抛出那个错误;它将忽略并丢弃未声明的名称空间:

require 'nokogiri'

# Here's a valid namespace used on an element:
doc = Nokogiri.XML("<root xmlns:a='hi'><a:foo/></root>")
puts doc.root
#=> <root xmlns:a="hi">
#=>   <a:foo/>
#=> </root>

# Here's a namespace that gets ignored
doc = Nokogiri.XML("<root xmlns:a='hi'><zzz:foo/></root>")
puts doc
#=> <root xmlns:a="hi">
#=>   <foo/>
#=> </root>

p doc.at('foo').namespace
#=> nil

# It's OK to declare namespaces later on
doc = Nokogiri.XML("<root><kid xmlns:zzz='yo'><zzz:foo/></kid></root>")
puts doc.root
#=> <root>
#=>   <kid xmlns:zzz="yo">
#=>     <zzz:foo/>
#=>   </kid>
#=> </root>

解析使用永远不会被声明为不可撤销的名称空间的XML文档会丢失它们。所以,即使您可以在任何节点上设置属性,如此...

mynode["xmlns:yay"]="someurl"

...它对您已解析的引用该命名空间名称的节点没有帮​​助。

现在,您的问题可能是您正在通过稍后声明的命名空间搜索节点?

p doc.at_xpath('//zzz:foo')
#=> in `evaluate': Undefined namespace prefix: //zzz:foo (Nokogiri::XML::XPath::SyntaxError)

如果是这样,你必须告诉Nokogiri命名空间:

p doc.at_xpath('//zzz:foo','zzz'=>'yo') 
#=> #<Nokogiri::XML::Element:0x80691894 name="foo" namespace=#<Nokogiri::XML::Namespace:0x806917cc prefix="zzz" href="yo">>

或者,如果您只是解析文档(以后不以XML格式发送它)并且您没有任何名称冲突,那么您可以作弊并抛弃所有名称空间以进行更简单的查询:

p doc.at_xpath('//foo')
#=> nil

doc.remove_namespaces!
p doc.at_xpath('//foo')
#=> #<Nokogiri::XML::Element:0x805fa2dc name="foo">