выбор text() с использованием предка или себя с несколькими выражениями XSLT XPATH

Учитывая XML:

<surmat>
  <unpack>
     <proc>
        <para>SERVICE UPON RECEIPT</para>
     </proc>
     <proc>
         <title></title>
         <para>Lift and remove</para>
     </proc>
   </unpack>
<surmat>

<surmat> имеет троих дочерних элементов unpack | chkeqp | processeqp, поэтому XML также может быть

<surmat>
  <processeqp>
     <proc>
        <para>SERVICE UPON RECEIPT</para>
     </proc>
     <proc>
         <title></title>
         <para>Lift and remove</para>
     </proc>
   </processeqp>
<surmat>

or

<surmat>
      <chkeqp>
         <title>SERVICE UPON RECEIPT</title>
         <proc>
             <title></title>
             <para>Lift and remove</para>
         </proc>
       </chkeqp>
    <surmat>

Используя XPATH или XSLT 2.0, я просто хочу проверить наличие SERVICE UPON RECEIPT в первом дочернем элементе <unpack>, <chkeqp> или <processeqp> из шаблона <title> и шаблонов <unpack/chkeqp/processeqp>, поскольку <title> является необязательным. (Мне нужно вставить SERVICE... и/или тег title, если они отсутствуют.) Дети chkeqp отличаются от unpack и processeqp.

Это вернет true, как и ожидалось:

contains(upper-case(ancestor-or-self::*[unpack or chkeqp or processeqp]),'SERVICE UPON RECEIPT')

но мне нужно проверить только первого ребенка, и я не мог понять синтаксис с помощью text().

то есть это не сработало:

contains(upper-case(ancestor-or-self::*[unpack or chkeqp or processeqp]/text()[1]),'SERVICE UPON RECEIPT')

или варианты этого:

contains(upper-case(ancestor-or-self::*[unpack or chkeqp or processeqp]/proc/para/text()[1]),'SERVICE UPON RECEIPT')

Если есть более эффективный способ сделать это, я был бы признателен, если бы вы им поделились! Спасибо.

Этот ответ решил мою проблему:

contains(upper-case(ancestor-or-self::*[(self::unpack or self::chkeqp or self::processeqp) and count(preceding-sibling::*[self::unpack or self::chkeqp or self::processeqp])=0]/descendant-or-self::para[1]),'SERVICE UPON RECEIPT')

person Caroline    schedule 03.01.2020    source источник


Ответы (2)


Чтобы проверить, является ли элемент-предок первым дочерним элементом surmat, вы можете подсчитать preceding-siblings:

contains(upper-case(ancestor-or-self::*[(self::unpack or self::chkeqp or self::processeqp) and count(preceding-sibling::*[self::unpack or self::chkeqp or self::processeqp])=0]/descendant-or-self::para[1]),'SERVICE UPON RECEIPT')

Это выражение возвращает true только для текста, совпадающего с первым элементом para, который является потомком элемента-предка unpack, chkeqp или processeqp элемента title.

person zx485    schedule 03.01.2020

Я не уверен, что правильно понял ваш вопрос, но, учитывая ваш xml, следующий xpath

contains(upper-case(//ancestor-or-self::*[name()=('unpack','chkeqp', 'processeqp')]/*[1]//para/text()),'SERVICE UPON RECEIPT')

возвращается

истинный

Это то, что вам нужно?

person Jack Fleeting    schedule 03.01.2020
comment
Думаю да, спасибо, буду тестировать во вторник. Я не хотел использовать para, потому что теги для chkeqp могли не иметь para в той же позиции. - person Caroline; 04.01.2020