我正在分析一个docx文件,并得到一个错误:"Undefined namespace prefix"。为了解决这个问题,我决定定义根标记中不存在的名称空间。
为此,我需要在根标记中插入一个带有"(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
以及获得具有添加的属性的新元素。然后我可以重写整个文件,但也许还有其他方法可以解决我的问题?
您需要提供有关导致该错误的操作的更多详细信息。仅仅解析一个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">