Возврат нескольких атрибутов узла с использованием XPATH - PullRequest
2 голосов
/ 15 января 2012

Мне нужно получить данные из XML, и я использую XPath, довольно новый для него, хотя мне это нравится.

Я извлекаю некоторые узлы на основе их атрибутов, например:

/cesAlign/linkGrp[@targType='s']

Теперь я хотел бы получить значение другого атрибута в узле:

/cesAlign/linkGrp[@targType='s']/@fromDoc

Однако, это возвращает только первый удар.Я хотел бы вернуть атрибут всех узлов, содержащих targType ='s'

Я думал о циклическом просмотре списка узлов и последующем чтении атрибута ... что-то вроде этого:

expr = xpath.compile("/cesAlign/linkGrp[@targType='s']/@fromDoc");
    NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);

    int i = 0;
    for (i = 0; i < nl.getLength(); i++) {
        expr = xpath.compile("/@fromDoc");
        System.out.println((String) expr.evaluate(nl, XPathConstants.STRING));
    }

Но я не уверен, есть ли лучший и более элегантный способ сделать это.

Вот пример XML:

<cesAlign version="1.0">
 <linkGrp targType="s" toDoc="mt/C2004310.01029701.xml.gz" fromDoc="en/C2004310.01029701.xml.gz">
 <linkGrp targType="s" toDoc="mt/C2004310.01029702.xml.gz" fromDoc="en/C2004310.01029702.xml.gz">
</cesAlign>

Спасибо!

Ответы [ 2 ]

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

Я думаю, вам придется перебирать найденные совпадения и извлекать значение атрибута для каждого элемента. Используйте "//cesAlign/linkGrp[@targType='s' and @fromDoc]" для выбора элементов. Вот элегантное решение Python:

#sample XML
xml = """
<cesAlign version="1.0">
 <linkGrp targType="s" toDoc="mt/C2004310.01029701.xml.gz" fromDoc="en/C2004310.01029701.xml.gz"/>
 <linkGrp targType="s" toDoc="mt/C2004310.01029702.xml.gz" fromDoc="en/C2004310.01029702.xml.gz"/>
 <linkGrp targType="s" toDoc="mt/C2004310.01029702.xml.gz" fromDoc="en/C2004310.01029703.xml.gz"/>
 <linkGrp targType="s" toDoc="mt/C2004310.01029702.xml.gz" fromDoc="en/C2004310.01029704.xml.gz"/>
 <linkGrp targType="s" toDoc="mt/C2004310.01029702.xml.gz" notFromDoc = "1"/>
 <linkGrp targType="s" toDoc="mt/C2004310.01029702.xml.gz" notFromDoc = "2"/>
</cesAlign>
"""
from lxml import etree
root = etree.fromstring(xml)
expr = root.xpath("//cesAlign/linkGrp[@targType='s' and @fromDoc]")
print "Matches:", len(expr)
for e in expr:
    print e.attrib["fromDoc"]

Вывод будет:

Matches: 4
en/C2004310.01029701.xml.gz
en/C2004310.01029702.xml.gz
en/C2004310.01029703.xml.gz
en/C2004310.01029704.xml.gz
0 голосов
/ 15 января 2012

В качестве альтернативы вы можете получить каждый требуемый атрибут с отдельным выражением XPath:

/cesAlign/linkGrp[@targType='s'][$x]/@fromDoc 

где $x должен быть заменен целым числом в интервале:

[1, count(/cesAlign/linkGrp[@targType='s'])]

Если у вас есть движок XPath 2.0, значения всех требуемых атрибутов можно получить с помощью одного выражения XPath 2.0 :

/cesAlign/linkGrp[@targType='s']/@fromDoc/string(.)

при вычислении этого выражения XPath 2.0 результатом является последовательность, содержащая строковые значения каждого требуемого атрибута fromDoc.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...