Может ли Nokogiri искать теги ?xml-stylesheet?

Мне нужно проанализировать таблицу стилей XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/templates/xslt/inspections/disclaimer_en.xsl"?>

Используя Нокогири, я пробовал:

doc.search("?xml-stylesheet").first['href']

но я получаю сообщение об ошибке:

`on_error': unexpected '?' after '' (Nokogiri::CSS::SyntaxError)

person John    schedule 22.08.2010    source источник


Ответы (2)


Nokogiri не может искать теги, которые являются инструкциями по обработке XML. Вы можете получить к ним доступ следующим образом:

doc.children[0]
person Daniel O'Hara    schedule 22.08.2010
comment
-1 У меня на Nokogiri 1.5.5 не работает: p Nokogiri.XML('<?xml version="1.0" encoding="UTF-8" ?><Foo />').children[0] #=> #<Nokogiri::XML::Element:0x323df0 name="Foo"> - person Phrogz; 28.08.2012
comment
Это действительно работало два года назад, но Нокогири можно было изменить изнутри. Я тестировал свой код, конечно же, в момент написания этого ответа. - person Daniel O'Hara; 28.08.2012
comment
Я действительно верю тебе. Я внутренне борюсь, что делать со старыми ответами на вопросы, которые когда-то были явно правильными, но которые больше не действительны. В настоящее время я считаю, что такие ответы должны быть отклонены, если существует альтернативный правильный ответ. Я не собираюсь наказывать вас (конечно, нет!), но показать, что ответ (уже не) полезен. - person Phrogz; 29.08.2012

Это не элемент XML; это XML "Инструкция по обработке". Вот почему вы не смогли найти его по вашему запросу. Чтобы найти его, вы хотите:

# Find the first xml-stylesheet PI
xss = doc.at_xpath('//processing-instruction("xml-stylesheet")')

# Find every xml-stylesheet PI
xsss = doc.xpath('//processing-instruction("xml-stylesheet")')

Видно в действии:

require 'nokogiri'
xml = <<ENDXML
  <?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="/templates/disclaimer_en.xsl"?>
  <root>Hi Mom!</root>
ENDXML
doc = Nokogiri.XML(xml)
xss = doc.at_xpath('//processing-instruction("xml-stylesheet")')
puts xss.name     #=> xml-stylesheet
puts xss.content  #=> type="text/xsl" href="/templates/disclaimer_en.xsl"

Поскольку инструкция обработки не является элементом, у нее нет атрибутов; вы не можете, например, запросить xss['type'] или xss['href']; вам нужно будет проанализировать содержимое как элемент, если вы этого хотите. Один из способов сделать это:

class Nokogiri::XML::ProcessingInstruction
  def to_element
    document.parse("<#{name} #{content}/>")
  end
end

p xss.to_element['href'] #=> "/templates/disclaimer_en.xsl"

Обратите внимание, что в Nokogiri или libxml2 существует ошибка, из-за которой XML-декларация для отображения в документе в виде Инструкция по обработке, если перед <?xml есть хотя бы один символ (может быть пробел). Вот почему в приведенном выше тексте мы специально ищем инструкции по обработке с именем xml-stylesheet.

Изменить: выражение XPath processing-instruction()[name()="foo"] эквивалентно выражению processing-instruction("foo"). Как описано в спецификации XPath 1.0:

Тест processing-instruction() может иметь аргумент Literal; в этом случае это верно для любой инструкции обработки, имя которой равно значению литерала.

Я отредактировал ответ выше, чтобы использовать более короткий формат.

person Phrogz    schedule 31.08.2012
comment
Обратите внимание: если вы знаете, что каждый PI находится в корне документа, а не является дочерним элементом другого элемента где-то глубоко в документе, вы можете сделать свой поиск гораздо более эффективным, используя xpath('/processing-instruction("xml-stylesheet"). - person Phrogz; 05.09.2012