Преобразование XSLT: поиск узлов и возвращение иерархических родителей - PullRequest
1 голос
/ 08 июня 2011

надеюсь, что об этом раньше не спрашивали, но у меня есть следующий XML:

<Company id="1000" name="Company1000">
   <Company id="1020" name="Company1020" />
   <Company id="1004" name="Company1004">
      <Company id="1005" name="Company1005" />
   </Company>
   <Company id="1022" name="Company1022" />
</Company>

У меня есть следующий XPath для поиска узлов: //*[contains(translate(@name, "ABCDEFGHJIKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "005")]

Я бы хотел, чтобы это вернулось:

<Company id="1000" name="Company1000">
   <Company id="1004" name="Company1004">
      <Company id="1005" name="Company1005" />
   </Company>
</Company>

Таким образом, это соответствует узлу Company1005 и всем его родителям. Я хотел бы, чтобы вышеприведенное также было возвращено, если бы я искал «100», что в этом случае соответствовало бы каждому элементу по очереди, но я явно не хочу дублирования узлов.

Я боролся с этим уже несколько часов, поэтому ваша помощь будет высоко оценена !!!

Спасибо.

1 Ответ

2 голосов
/ 09 июля 2011

Решение состоит в том, чтобы скопировать только узлы-потомки или собственные узлы, которые соответствуют вашему требованию (содержащие нужную строку).

Посмотрите на это изображение внизу этой страницы для осей XPathвам нужно.

Длинная версия:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" encoding="UTF-8" indent="yes"/>

<xsl:strip-space elements="*"/>

<!-- Default: copy everything -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- just copy Company which descendant-or-self contain the matching string -->
<xsl:template match="Company">
    <xsl:if test="descendant-or-self::Company[contains(translate(@name, 'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '005')]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

Короткая версия:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" encoding="UTF-8" indent="yes"/>

<xsl:strip-space elements="*"/>

<!-- Default: copy everything -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- do not copy Company which do not have a descendant-or-self matching string -->
<xsl:template match="Company[not(descendant-or-self::Company[contains(translate(@name, 'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '005')])]"/>

</xsl:stylesheet>

Вывод вашего xml:

<?xml version="1.0" encoding="UTF-8"?>
<Company id="1000" name="Company1000">
  <Company id="1004" name="Company1004">
    <Company id="1005" name="Company1005"/>
  </Company>
</Company>
...