Добавить атрибут к тегу xml в уже существующем XML-файле - PullRequest
1 голос
/ 18 января 2012

Я анализирую файл docx и получаю сообщение об ошибке: «Неопределенный префикс пространства имен». Чтобы решить эту проблему, я решил определить пространство имен, которого нет в корневом теге.

Для этого мне нужно вставить атрибут «xmlns: wp» со значением «(url)» в корневой тег.

Как я могу сделать это, используя драгоценный камень Нокогири?

Или, если с другим камнем легче, просто покажи мне как. Я добавляю атрибут к элементу 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 Ответ

1 голос
/ 19 января 2012

Вы должны предоставить более подробную информацию о том, что вы делаете, что вызывает эту ошибку.Простой анализ 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">
...