Получить значение атрибута родителей, если у ребенка нет определенного значения атрибута

У меня есть xml-файл в Linux, который я хочу обработать. Мне нужно получить все идентификаторы родительских узлов на основе его дочерних элементов. Здесь я хочу получить все идентификаторы «a», у которых есть «c», без ключа f.g.

<a id="11111">
  <b>
    <c key="d.e">stuff1</c>
    <c key="f.g">stuff2</c>
    <c key="j.k">stuff4</c>
  </b>
</a>
<a id="22222">
  <b>
    <c key="d.e">stuff1</c>
    <c key="h.i">stuff3</c>
    <c key="j.k">stuff4</c>
    <c key="l.m">stuff5</c>
  </b>
</a>
<a id="33333">
  <b>
    <c key="c.d">stuff0</c>
    <c key="d.e">stuff1</c>
    <c key="h.i">stuff3</c>
    <c key="j.k">stuff4</c>
    <c key="l.m">stuff5</c>
  </b>
</a>

В этом случае я должен получить 22222 и 33333. Я не совсем уверен, как написать для этого xpath.


person aedan    schedule 26.06.2020    source источник


Ответы (3)


Я думаю, вы ищете что-то вроде:

//a[not(.//c[@key="f.g"])]/@id

что можно перевести как: найти любой узел <a>, который НЕ имеет дочернего узла <c>, который сам имеет атрибут с именем key, который сам имеет значение атрибута f.g.

person Jack Fleeting    schedule 26.06.2020
comment
Я получаю эту ошибку, что это значит? Ошибка XPath: незаконченный литерал xmlXPathEval: оценка не удалась Ошибка оценки XPath - person aedan; 26.06.2020
comment
@aedan Трудно сказать, не видя реального xml; но давайте попробуем так: какую именно команду xmllint вы использовали? - person Jack Fleeting; 26.06.2020

Вы можете фильтровать по (не):

//a[[not(@key = 'f.g')]]

Он вернет вам нужные элементы «a», но я не знаю, как получить их идентификаторы.

person Sergii Dmytrenko    schedule 26.06.2020
comment
Хм, я узнал, как получить идентификаторы, но, похоже, они не работают. Это xpath, который я сейчас пробую //a[./b/c[not[@key='f.g']]]/@id - person aedan; 26.06.2020
comment
используйте '(' и ')' вместо '[' и ']': //a[.//c[not(@key='f.g')]]/@id - person Sergii Dmytrenko; 26.06.2020

Ответ @ Джека Флитинга, вероятно, лучшее решение. В качестве альтернативы (более потребляющей):

//c[not(@key="f.g" or preceding-sibling::c[@key="f.g"] or following-sibling::c[@key="f.g"])]/ancestor::a

Ищите элементы c, в которых сам элемент, а также предшествующие или последующие одноуровневые элементы содержат атрибут, отличный от @key="f.g". Затем выберите их a предков.

person E.Wiest    schedule 26.06.2020