Как игнорировать пространства имен в XPath 1.0?

#xml #xpath #xpath-1.0

#xml #xpath #xpath-1.0

Вопрос:

У меня возникают серьезные проблемы при попытке понять магию XPath.

В принципе, у меня есть такой XML:

 <a>
    <b>
        <c/>
    </b>
</a>
  

Теперь я хочу посчитать, сколько у нас B, без C. Это можно легко сделать с помощью следующего XPath:

 count(*/b[not(descendant::c)])
  

Теперь вопрос прост: как мне сделать то же самое, игнорируя любые пространства имен?

Я бы предположил, что это было что-то вроде этого?

 count(*/[local-name()='b']/[not(descendant::[local-name()='c'])])
  

Но это неверно. Каким будет эквивалентный XPath, как у меня выше, но который игнорирует пространства имен?

Комментарии:

1. Если вы спрашиваете конкретно о XPath 1.0, пожалуйста, проясните это в своем вопросе. В XPath 2.0 и 3.0 вы можете написать *:c для выбора элементов с локальным именем c в любом пространстве имен.

2. OP явно обозначил вопрос как xpath-1.0, но я, вероятно, должен был представить это в правке заголовка, которую я сделал. Исправлено.

3. Хорошо, я виноват. Я предположил, что достаточно пометить тему как xpath-1.0. Я обязательно добавлю это в тему в следующий раз.

Ответ №1:

Данный XPath,

 count(*/b[not(descendant::c)])
  

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

 count(*[local-name()='b' and not(descendant::*[local-name()='c'])])
  

Обратите внимание, что обычно лучше не уничтожать пространства имен, а правильно работать с ними, назначая префиксы пространства имен и используя их в вашем выражении XPath.

Комментарии:

1. Милая, спасибо! Пришлось потратить немного больше времени, задаваясь вопросом, когда реальный сценарий имеет несколько элементов до этого решения, но в конце концов я туда попал. И я слышал о пространствах имен, но в этом случае мы проверили XML-способ перед этой частью. По сути, это просто проверка кода, которую мы специально не хотим делать зависящей от пространства имен.