XPath 1.0, чтобы найти родственника узла атрибута, имя которого основано на атрибуте, но имеет суффикс - PullRequest
1 голос
/ 17 марта 2020

Учитывая следующее Xml:

<Root><Foo Bar="" Bar_Baz="12" /></Root>

Существует ли оператор XPath (использующий только функции версии 1.0), который может вернуть Root/Foo/@Bar, если существует некоторый родственный атрибут, начинающийся с Bar (определено по контексту) и заканчивается на _Baz, где этот узел имеет значение 12?

Bar должен быть анонимным - XPath не должно волновать, как он называется - но как бы он ни назывался, если он возвращается или нет, должно быть определено, существует ли X_Baz, и имеет значение 12.

Я искал что-то вроде:

//@*[sibling::@*[concat(local-name(), '_Baz') = '12']

Но довольно очевидно, что это будет просто сравнить текст Bar_Baz до 12, а не значение этого родственного атрибута.

Я использую это, используя класс. Net XmlDocument, что означает, что я ограничен Microsoft XPath 1.0 реализации, поэтому, пожалуйста, не используйте последующие версии spe c!

EDIT: в соответствии с комментарием, требующим более разнообразный набор примеров, см. ниже:

<Root>
  <Item Foo="" Foo_Baz="12">Yes - @Foo_Baz is 12, and @Foo exists</Item>
  <Item Bar="" Bar_Baz="12">Yes - @Bar_Baz is 12, and @Bar exists</Item>
  <Item Foo="" Foo_Baz="1">No - Foo_Baz != 12<Item>
  <Item Baz="" Foo_Baz="12">No - No @Foo to return</Item>
  <Item Foo_Baz="12">No - No @Foo to return</Item>
  <Item Foo="" Foo_Haz="12">No - No @Foo_Baz node to check the value of</Item>
</Root>

Изменить 2: Глядя на первый Несколько предложенных ответов, я думаю, есть кое-что, что мне неясно: имена, Foo или Bar, неизвестны. известны только *1025*:

  • Есть один или несколько атрибутов с суффиксом _Baz, значение которых 12
  • . Они могут есть братья и сестры, чье полное имя совпадает с предшествующим
  • Если они это сделают, то этот брат - это узел, которому я хочу соответствовать, при условии атрибут _Baz имеет значение 12

Ответы [ 2 ]

0 голосов
/ 18 марта 2020

Другой вариант:

//item[substring-after(local-name(./@*[last()]),"_")="baz" and ./@*[last()]="12"][local-name(./@*[1])=substring-before(local-name(./@*[last()]),"_")]

Кратчайшая форма:

//item[@foo or @bar][@bar_baz="12" or @foo_baz="12"]

РЕДАКТИРОВАТЬ: Массивный и ужасный XPath здесь, но он должен работать. Он поддерживает до 5 атрибутов на элемент и независимо от положения этих атрибутов внутри каждого тега элемента.

//item[contains(local-name(@*[1]),"_baz") and @*[1]=12][local-name(@*[1])=substring-before(local-name(@*[1]),"_")]|//item[contains(local-name(@*[1]),"_baz") and @*[1]=12][local-name(@*[3])=substring-before(local-name(@*[1]),"_")]|//item[contains(local-name(@*[1]),"_baz") and @*[1]=12][local-name(@*[4])=substring-before(local-name(@*[1]),"_")]|//item[contains(local-name(@*[1]),"_baz") and @*[1]=12][local-name(@*[5])=substring-before(local-name(@*[1]),"_")]|//item[contains(local-name(@*[2]),"_baz") and @*[2]=12][local-name(@*[1])=substring-before(local-name(@*[2]),"_")]|//item[contains(local-name(@*[2]),"_baz") and @*[2]=12][local-name(@*[3])=substring-before(local-name(@*[2]),"_")]|//item[contains(local-name(@*[2]),"_baz") and @*[2]=12][local-name(@*[4])=substring-before(local-name(@*[2]),"_")]|//item[contains(local-name(@*[2]),"_baz") and @*[2]=12][local-name(@*[5])=substring-before(local-name(@*[2]),"_")]|//item[contains(local-name(@*[3]),"_baz") and @*[3]=12][local-name(@*[1])=substring-before(local-name(@*[3]),"_")]|//item[contains(local-name(@*[3]),"_baz") and @*[3]=12][local-name(@*[3])=substring-before(local-name(@*[3]),"_")]|//item[contains(local-name(@*[3]),"_baz") and @*[3]=12][local-name(@*[4])=substring-before(local-name(@*[3]),"_")]|//item[contains(local-name(@*[3]),"_baz") and @*[3]=12][local-name(@*[5])=substring-before(local-name(@*[3]),"_")]|//item[contains(local-name(@*[4]),"_baz") and @*[4]=12][local-name(@*[1])=substring-before(local-name(@*[4]),"_")]|//item[contains(local-name(@*[4]),"_baz") and @*[4]=12][local-name(@*[3])=substring-before(local-name(@*[4]),"_")]|//item[contains(local-name(@*[4]),"_baz") and @*[4]=12][local-name(@*[4])=substring-before(local-name(@*[4]),"_")]|//item[contains(local-name(@*[4]),"_baz") and @*[4]=12][local-name(@*[5])=substring-before(local-name(@*[4]),"_")]|//item[contains(local-name(@*[5]),"_baz") and @*[5]=12][local-name(@*[1])=substring-before(local-name(@*[5]),"_")]|//item[contains(local-name(@*[5]),"_baz") and @*[5]=12][local-name(@*[3])=substring-before(local-name(@*[5]),"_")]|//item[contains(local-name(@*[5]),"_baz") and @*[5]=12][local-name(@*[4])=substring-before(local-name(@*[5]),"_")]|//item[contains(local-name(@*[5]),"_baz") and @*[5]=12][local-name(@*[5])=substring-before(local-name(@*[5]),"_")]

Рабочий образец (4 выбранных узла):

XPath Horror

0 голосов
/ 17 марта 2020

Строго говоря, с точки зрения xpath, это выражение

//Item[attribute::*[contains(local-name(), '_Baz')]='12'][attribute::*[local-name()='Foo'] | attribute::*[local-name()='Bar']]

должно дать вам желаемый результат.

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