Как бороться с "<?" аннотация в XML-файле с Python

Кто-то знает, как бороться с такого рода аннотацией XML с Pythonэто мой первый раз, когда я увидел это

Мне нужно запросить этот вид "элемента", чтобы получить resource-uuid значение.

Благодарю за любую помощь.

4 ответа

Решение

Спасибо всем, я узнал об инструкции по обработке и с этим я провел исследование о том, как с ней обращаться, ниже я позволил себе поцарапаться, если кому-то это понадобится:

from lxml import etree

...

file = 'path/to/file.xml'
tree = etree.parse(file)
result = tree.xpath('//processing-instruction("link")')
for pi in result:
    # Each pi is a processing instruction tagged as 'link'
    if pi.get('type').__str__() == 'ResourceImport':
        # PI with type = ResourceImport
        print pi.text # Check the text of tis PI

С помощью lxml Библиотека легко получить инструкции обработки с помощью XPath.

Я надеюсь, что этот фрагмент кода поможет людям, которые попали сюда из-за этого вопроса.

Вы должны различать инструкцию обработки и объявление xml

Оба написаны одинаково: <?SomeName SomeContent ?>,

Подробности в разделе 2.6!

Хотя xml-объявление должно быть на первом месте и начинается с <?xml другие инструкции по обработке могут появиться (почти) в любом месте XML.

Инструкция обработки должна иметь имя, в то время как содержание не ограничено формально, как содержимое элемента. Это свободный текст...

Так что это правильно сформированный XML:

<root>
  <a>test</a>
  <?piName some test?>
</root>

Я не работаю с Python, но это вернет ваш PI в SQL-Server:

DECLARE @xml XML=
N'<root>
    <a>test</a>
    <?link id="752760" resource-uuid="UUID-9f0575a3-1847-1cde-fd35-f18014fdecf3" resource-id="570935" resource-type="fork" type="ResourceLink"?>
  </root>';

SELECT @xml.query('/root/processing-instruction("link")');

Даже если ваш контент выглядит как атрибуты: в PI контент - это свободный текст. Таким образом, вы должны разобрать вашу информацию из содержания...

Этот ответ может помочь вам.

Ссылка, на которую вы ссылаетесь, называется инструкцией обработки.

В инструкциях по обработке очень часто используется keyword="value" синтаксис похож на атрибуты элемента XML, но, к сожалению, это всего лишь соглашение, а не что-то присущее XML, поэтому вам придется самостоятельно анализировать содержимое для извлечения атрибутов. (Саксонский имеет функцию saxon:get-pseudo-attribute() за это).

Если вы находитесь в Python, возможно, проще выполнить этот дополнительный этап синтаксического анализа в коде Python, а не в коде XPath - если только вам на самом деле не нужно значение как часть более крупного выражения XPath, и в этом случае детализация зависит от того, используете ли вы XPath или XQuery и какая версия.

Если ваш процессор поддерживает XQuery 3.1, вот один из способов решения проблемы:

declare function local:values($pi) {
  map:merge(
    for $pair in tokenize($pi)
    let $key := substring-before($pair, '=')
    let $value := replace(substring-after($pair, '='), '^"|"$', '')
    return map:entry($key, $value)
  )
};

let $xml := document {
  <xml>
    <?link id="752760" resource-uuid="UUID-9f0575a3-1847-1cde-fd35-f18014fdecf3"
      resource-id="570935" resource-type="fork" type="ResourceLink"?>
  </xml>
}
for $pi in $xml//processing-instruction('link')
let $values := local:values($pi)
return $values?resource-uuid

Еще одно решение для старых версий XQuery:

let $xml := document {
  <xml>
    <?link id="752760" resource-uuid="UUID-9f0575a3-1847-1cde-fd35-f18014fdecf3"
      resource-id="570935" resource-type="fork" type="ResourceLink"?>
  </xml>
}
for $pi in $xml//processing-instruction('link')
for $pair in tokenize($pi, '\s+')[substring-before(., '=') = 'resource-uuid']
return replace(substring-after($pair, '='), '^"|"$', '')

Оба фрагмента кода работают в предположении, что все значения в ваших инструкциях по обработке составлены, как в вашем примере (ключи и значения, разделенные знаком равенства, значения, заключенные в двойные кавычки).

Другие вопросы по тегам