Как я могу получить родительский узел на основе нескольких значений дочерних узлов? - PullRequest
1 голос
/ 26 августа 2011
<parents>
 <parent>
    <item>
        <name>200</name>
    </item>
    <item>
        <name>201</name>
    </item>
    <item>
        <name>204</name>
    </item>
 </parent>
 <parent>
     <item>
        <name>203</name>
     </item>
 </parent>
</parents>

Мне нужен первый parent узел, потому что у меня есть список идентификаторов, которые соответствуют элементам.Учтите это:

list = ['200', '201'];

Поскольку 200 находится в первом узле parent, я хочу этот узел parent.Если 200 не существует, я все равно получу родительский узел, потому что 201 является значением /name/text(), находящимся в первом parent.

Мое единственное требование - мне нужно захватить узел parent, если даже one идентификаторов в моем list найдено.

В настоящее время я тестирую тольково-первых, вот так:

//name/child::text()[.="' . $firstKey . '"]/../../../../

Где $firstKey - ссылка на первый элемент в списке, 200.Это не идеально, потому что он проверяет не все значения, а только первое.

Ответы [ 3 ]

1 голос
/ 27 августа 2011

I. Решение XPath 1.0 с использованием XSLT 1.0 в качестве хоста :

Использование:

/*/parent[item/name = $vList]

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

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

 <my:list>
  <val>200</val>
  <val>201</val>
 </my:list>

 <xsl:variable name="vList" select=
     "document('')/*/my:list/*"/>

 <xsl:template match="/">
     <xsl:copy-of select="*/parent[item/name = $vList]"/>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<parents>
    <parent>
        <item>
            <name>200</name>
        </item>
        <item>
            <name>201</name>
        </item>
        <item>
            <name>204</name>
        </item>
    </parent>
    <parent>
        <item>
            <name>203</name>
        </item>
    </parent>
</parents>

дает желаемый, правильный результат :

<parent>
   <item>
      <name>200</name>
   </item>
   <item>
      <name>201</name>
   </item>
   <item>
      <name>204</name>
   </item>
</parent>

Примечание : Вы можете передать то, что сейчас <my:list>, в качестве параметра преобразования.

II. Использование XPath 2.0 :

/*/parent[item/name = ('200', '201')]

Проверка на основе XSLT 2.0 ниже "

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
     <xsl:copy-of select="*/parent[item/name = ('200', '201')]"/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному XML-документу (см. Выше), получается тот же правильный результат.

0 голосов
/ 27 августа 2011

Если у вас XSLT 2.0, вы можете сказать

<xsl:variable name="list" select="(200, 201)" />
<xsl:variable name="theParent" select="(//parent[item/name = $list])[1]" />

= работает как экзистенциальное сравнение, возвращая true, если какой-либо элемент в наборе узлов на левой стороне равен любому элементу впоследовательность на правой стороне =.

(не проверено.)

0 голосов
/ 26 августа 2011

Нечто подобное может помочь:

//parent[.//item[name[text()='200' or text()='201']]]

Вы должны будете создать самый внутренний предикат (с text()='200' or ...) программно. Я не уверен, в каком контексте вы используете это, но так как вы используете ссылку на переменную, я предполагаю XSLT. Я посмотрю, есть ли что-нибудь более подходящее ...

РЕДАКТИРОВАТЬ : Единственное, о чем я могу думать, - это объединить все ваши ключи с каким-то символом, который, как вы уверены, никогда не будет содержать разделитель. Например:

200#201#...

Затем используйте функцию XPath contains:

//parent[.//item[name[contains('200#201#...', normalize-space(text()))]]]

Тогда первым аргументом метода содержит ваши соединенные ключи, возможно, переданные в виде переменной. Функция string-join была бы хороша для этого, но я полагаю, что она доступна только в XPath 2.0.

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