Как удалить определенные узлы в XML с помощью xslt? - PullRequest
1 голос
/ 21 марта 2011

Кто-нибудь знает, как сделать следующее преобразование, используя xslt?

Исходный код:

<?xml version="1.0" encoding="UTF-8"?>
<body>
  <termEntry id="1">
   <langSet lang="eng-us">
    <ntig>
     <termGrp>
      <term></term>
     </termGrp>
    </ntig>
    <ntig>
     <termGrp>
      <term></term>
     </termGrp>
    </ntig>
   </langSet>

   <langSet lang="ara-ae">
    <ntig>
     <termGrp>
      <term>123</term>
     </termGrp>
    </ntig>
   </langSet>
</termEntry>

<termEntry id="2">
 <langSet lang="eng-us">
  <ntig>
   <termGrp>
    <term></term>
   </termGrp>
  </ntig>
  <ntig>
   <termGrp>
    <term></term>
   </termGrp>
  </ntig>
  <ntig>
   <termGrp>
    <term>123</term>
   </termGrp>
  </ntig>
 </langSet>
</termEntry>
</body>

Запрос: 1.Если значение в <term></term> равно нулю \ пусто, удалите его родительский узел, а именно

<ntig></ntig>

2. Таким образом, если все теги <term> пусты, удалите весь узел <langset>.

Ожидаемый результат

<?xml version="1.0" encoding="UTF-8"?>
<body>
  <termEntry id="1">

   <langSet lang="ara-ae">
    <ntig>
     <termGrp>
      <term>123</term>
     </termGrp>
    </ntig>
   </langSet>
  </termEntry>

  <termEntry id="2">
   <langSet lang="eng-us">
    <ntig>
     <termGrp>
      <term>123</term>
     </termGrp>
    </ntig>
   </langSet>
 </termEntry>
</body>

Ответы [ 2 ]

3 голосов
/ 21 марта 2011

Преобразование идентичности плюс пара простых пустых шаблонов - вот что вам нужно здесь. Вы хотите скопировать все свои входные данные в выходные данные, если они не соответствуют вашим критериям, и в этом случае вы хотите подавить их.

Таблица стилей, такая как:

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

    <xsl:template match='@*|node()'>
        <xsl:copy>
            <xsl:apply-templates select='@*|node()'/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ntig[descendant::term[. = '']]"/>
    <xsl:template match="langSet[not(descendant::term[. != ''])]"/>

</xsl:stylesheet>

сделает то, что вам нужно. Шаблон, который соответствует элементам ntig, будет подавлять эти элементы с пустыми term внуками. Шаблон, соответствующий элементам langSet, подавляет те элементы langSets, в которых нет элементов-потомков term, имеющих содержимое.

1 голос
/ 21 марта 2011

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

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

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

 <xsl:template match="ntig[not(*/term[string-length()>0])]"/>
 <xsl:template match="langSet[not(*/*/term[string-length()>0])]"/>
</xsl:stylesheet>

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

<body>
    <termEntry id="1">
        <langSet lang="eng-us">
            <ntig>
                <termGrp>
                    <term></term>
                </termGrp>
            </ntig>
            <ntig>
                <termGrp>
                    <term></term>
                </termGrp>
            </ntig>
        </langSet>
        <langSet lang="ara-ae">
            <ntig>
                <termGrp>
                    <term>123</term>
                </termGrp>
            </ntig>
        </langSet>
    </termEntry>
    <termEntry id="2">
        <langSet lang="eng-us">
            <ntig>
                <termGrp>
                    <term></term>
                </termGrp>
            </ntig>
            <ntig>
                <termGrp>
                    <term></term>
                </termGrp>
            </ntig>
            <ntig>
                <termGrp>
                    <term>123</term>
                </termGrp>
            </ntig>
        </langSet>
    </termEntry>
</body>

дает желаемый результат :

<body>
   <termEntry id="1">
      <langSet lang="ara-ae">
         <ntig>
            <termGrp>
               <term>123</term>
            </termGrp>
         </ntig>
      </langSet>
   </termEntry>
   <termEntry id="2">
      <langSet lang="eng-us">
         <ntig>
            <termGrp>
               <term>123</term>
            </termGrp>
         </ntig>
      </langSet>
   </termEntry>
</body>

Объяснение

  1. Правило идентификации (шаблон) копирует каждый узел "как есть".

  2. Шаблон, переопределяющий правило идентификации для ntig[not(*/term[string-length()>0])], имеет пустое тело - это фактически игнорирует (удаляет) любой элемент ntig, который не имеет хотя бы одного term внука с положительным string-length() .

  3. Шаблон, переопределяющий правило идентификации для langSet[not(*/*/term[string-length()>0])], имеет пустое тело - это фактически игнорирует (удаляет) любой элемент langSet, который не имеет хотя бы одного term правнука с положительным string-length().

Обратите внимание , что указание таких шаблонов нарушает определение проблемы:

<xsl:template match="ntig[descendant::term[. = '']]"/> 
<xsl:template match="langSet[not(descendant::term[. != ''])]"/>   

Поскольку требование состоит в том, чтобы "если значение в равно null \ empty, удалите его grandparent node".

Однако первый шаблон выше удаляет не только прародителя ntig, но и любого предка ntig.

Текущее решение не допускает такой ошибки .

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