XPath — выбор узла на основе значения родственного узла при использовании local-name()

По причинам, выходящим за рамки этого вопроса, мне нужно иметь возможность обрабатывать несколько XML-документов с одинаковой структурой, но принадлежащих к разным пространствам имен (не спрашивайте).

Чтобы достичь этого, я очень привык использовать xpath, подобный следующему, для многих моих вариантов выбора значений:

//*[local-name()='apple']/*[local-name()='flavor']/text()"

Мое непонимание предикатов не позволяет мне выбрать значение узла на основе значения родственного узла. Рассмотрим следующий xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<fruit>
    <apple>
        <kind>Red Delicious</kind>
        <flavor>starchy</flavor>
    </apple>
    <apple>
        <kind>Granny Smith</kind>
        <flavor>tart</flavor>
    </apple>
    <apple>
        <kind>Pink Lady</kind>
        <flavor>sweet</flavor>
    </apple>
</fruit>

Допустим, я хочу написать xpath, который будет выбирать вкус яблока Granny Smith. Хотя обычно я делаю что-то вроде:

//apple[kind/text()='Granny Smith']/flavor/text()

Я не могу понять, как объединить концепцию использования local-name(), чтобы быть независимым от пространства имен, при этом выбирая узел на основе значения родственного элемента.

Короче говоря, какой xpath необходим для возврата «пирога» независимо от того, к какому пространству имен принадлежит входной XML-документ фруктов?


person Russ    schedule 13.04.2017    source источник
comment
Я не совсем уверен, что понимаю, но //*[содержит(.,'tart')] - это то, что я думаю, вы ищете. Однако, чтобы быть более конкретным: //apple[contains(@flavor, 'tart')] вернет рассматриваемое яблоко, предполагая, что есть другие фрукты, которые также могут иметь дочерний элемент тега аромата.   -  person Bill Hileman    schedule 13.04.2017
comment
Мне нужен эквивалент этого xpath, который будет игнорировать пространство имен и работать для любого фруктового xml независимо от того, к какому пространству имен он принадлежит (если структура указана выше): //apple[kind/text()='Granny Smith']/ флейвор/текст() давайте предположим, что мы не знаем, что такое флейвор ради аргумента   -  person Russ    schedule 13.04.2017
comment
Думаю, теперь я понимаю. Я могу рассказать вам, как я сделал бы это на Java, если это поможет: //*[local-name()='type']/*[local-name()='property']/../name() ='output']/text().replace(тип,яблоко).replace(свойство,вид).replace(выход,аромат); (воздушный код, непроверенный)   -  person Bill Hileman    schedule 13.04.2017


Ответы (1)


Мне нужно иметь возможность обрабатывать несколько XML-документов одинаковой структуры, но принадлежащих к разным пространствам имен (не спрашивайте)

Мой предпочтительный способ справиться с этим — сначала преобразовать данные для использования единого пространства имен, а затем выполнить правильное преобразование. Таким образом (а) реальное преобразование становится намного проще, (б) вся логика преобразования пространства имен помещается в одном месте и (в) логика преобразования пространства имен может использоваться повторно — вы можете использовать одно и то же преобразование независимо от того, как впоследствии будут выглядеть данные. использоваться.

person Michael Kay    schedule 13.04.2017