XSL выбрать все узлы, где не узел другого узла - PullRequest
1 голос
/ 09 августа 2010

Это мой xml

<element1> <subel1/> </element1> <element2> <subel2/> </element2> <element3> <subel3/> </element3> <criteria> <subel3/> </criteria>

как я могу выбрать все узлы с xsl, которые не входят в подузлы критериев?как это

 <subel1/> <subel2/>

Как это сделать?

Если xml форматируется как:

<element1> 
<el> subel1 </el>
</element1>
 <element2> 
<el> subel2 
</el> 
</element2> 
<element3> 
<el> subel3 </el> 
</element3> 
<criteria> 
<subel3/> 
</criteria>

Ответы [ 3 ]

6 голосов
/ 10 августа 2010

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:for-each select=
  "/*/*[not(self::criteria)]/*">
   <xsl:copy-of select=
   "self::node()[not(/*/criteria/*[name()=name(current())])]"/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

при применении к этому документу XML (на основе предоставленного фрагмента XML, но обернул фрагмент XML в верхний элемент идобавил еще одного потомка к criteria, чтобы сделать задачу менее тривиальной):

<t>
    <element1>
        <subel1/>
    </element1>
    <element2>
        <subel2/>
    </element2>
    <element3>
        <subel3/>
    </element3>
    <criteria>
        <subel3/>
        <subel1/>
    </criteria>
</t>

дает желаемый результат (другой опубликованный ответ на момент написания этой статьи не дает правильного результата):

<subel2/>

Пошаговое объяснение :

  1. Выражение XPath:

    /*/*[not(self::criteria)]/*

выбирает каждый элемент, родительским элементом которого является элемент без имени "criteria" и который является дочерним элементом верхнего элемента документа.

В инструкции <xsl:for-each> мы проверяем, есть ли у текущего узла имя, которое не является ни одним из имен каких-либо дочерних элементов criteria, и копируем только такой узел:

self::node()[not(/*/criteria/*[name()=name(current())])]

Это выражение XPath выбирает текущий узел (self::node()), только если не существует дочернего элемента /*/criteria, имя которого совпадает с именем текущего узла (not(/*/criteria/*[name()=name(current())])).

Здесь мы используем тот факт, что not(someNode-Set) равен false(), только если набор узлов someNode-Set пуст.

2 голосов
/ 09 августа 2010

Самый простой способ сделать это - создать выражение xpath, которое сверяется с узлами критериев. Например:

Шаг 1: Далее будут выбраны все узлы, которые не находятся в области критериев (поэтому все узлы, у которых нет родителя с именем «критерии»)

//*[name(..) != 'criteria'] 

Шаг 2: Отфильтруйте все узлы, которые также появляются в разделе critera

//*[name(..) != 'criteria' and not(name(//criteria/*) = name(.))]

Теперь последний оператор выберет все узлы, которые не соответствуют узлу критерия. Но вам просто нужны подчиненные узлы, поэтому мы можем изменить селектор так, чтобы он захватывал только те элементы, которые являются «вложенными элементами» или конечными элементами, которые не имеют дочерних узлов.

//*[name(..) != 'criteria' and not(name(//criteria/*) = name(.)) and not(*)]

Итак, вот разбивка каждого из наших условных выражений еще раз:

name (..)! = 'Критерии' - ограничения на узлы, которых нет в разделе критериев

not (имя (// критерии / *) = имя (.)) - ограничения для узлов, которые не имеют того же имени, что и узел в разделе критериев

а не (*) - ограничения на узлы, у которых нет дочерних узлов (так что это конечные узлы, которые вы хотите.)

Так что если бы вы делали что-то вроде:

<xsl:for-each select="//*[name(..) != 'criteria' and not(name(//criteria/*) = name(.)) and not(*)]">
 <xsl:value-of select="name(current())"/> :
</xsl:for-each>

В приведенном выше примере это выглядело бы так:

subel1 : subel2

Надеюсь, это поможет.

Приветствия

Casey

1 голос
/ 09 августа 2010

вы не пропустили xmlcode?было бы легче помочь, если вы введете код и в редакторе пометите его как исходный код (кнопка с «101 010»)

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