Мое выражение XPATH не работает должным образом - PullRequest
3 голосов
/ 09 января 2012

Я использую это выражение xpath для вывода списка всех элементов «NON TEST»:

/Items/Item[State!='TEST']/Name

Обычно входной XML выглядит следующим образом, и все отлично работает:

<Items>
  <Item>
    <Name>Item1</Name>
    <State>ACTIVE</State>
  </Item>
  <Item>
    <Name>Item2</Name>
    <State>TEST</State>
  </Item>
</Items>

Но когда пропущен элементЭлемент состояния, который выражение xpath ничего не выделяет:

<Items>
  <Item>
    <Name>Item1</Name>
  </Item>
  <Item>
    <Name>Item2</Name>
  </Item>
</Items>

Пожалуйста, как мне изменить выражение xpath, чтобы оно также работало, когда элемент State не существует?Если элемент State не существует, Item рассматривается как элемент "NON TEST".У меня нет возможности изменить структуру XML.

1 Ответ

5 голосов
/ 09 января 2012

Используйте следующее выражение:

/Items/Item[not(State='TEST')]/Name

Разница в том, что State!='TEST' выбирает те элементы, которые имеют любой элемент State, строковое значение которого не равно TEST, а not(State='TEST') выбирает всеэлементы, не имеющие элемента State, строковое значение которого равно TEST (независимо от того, существует State или нет).Это тонкое, но существенное отличие.

От спецификации :

Если один объект для сравнения является набором узлов, а другой - строкой,тогда сравнение будет истинным в том и только в том случае, если в наборе узлов есть узел, так что результат выполнения сравнения строкового значения узла и другой строки будет истинным.

Кроме того, представьте следующий ввод:

<Items>
    <Item>
        <Name>Item1</Name>
        <State>blah</State>
        <State>TEST</State>
    </Item>
    <Item>
        <Name>Item2</Name>
        <State>TEST</State>
    </Item>
</Items>

Это выражение:

/Items/Item[State!='TEST']/Name

... выберет первый Item элемент Name, поскольку он содержит хотя бы один элемент State, не имеющий значения TEST.

Однако это выражение:

/Items/Item[not(State='TEST')]/Name

... не выбирает элементы.Эта вторая форма очень часто является тем, что вы хотите.

См. Эту заметку из спецификации :

ПРИМЕЧАНИЕ: Если $xпривязан к набору узлов, тогда $x="foo" не означает то же самое, что и not($x!="foo"): первое истинно тогда и только тогда, когда некоторый узел в $x имеет строковое значение foo;последнее верно тогда и только тогда, когда все узлы в $x имеют строковое значение foo.

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