Как отсортировать некоторые элементы XML в соответствии с их зависимостями, используя XSLT? - PullRequest
3 голосов
/ 26 сентября 2011

Я хочу отсортировать следующий XML-файл:

<root>
  <element name="a" depends="b,c" />
  <element name="b" depends="c" />
  <element name="c" />
</root>

С этим результатом:

<root>
  <element name="c" />
  <element name="b" depends="c" />
  <element name="a" depends="b,c" />
</root>

Мои зависимости можно смоделировать с помощью дерева (без цикла). зависимость = "b, c" означает, что зависит как от b, так и от c. Я спрашиваю хороший способ сделать это с помощью XSLT. Возможно, у вас есть идеи? Спасибо!

1 Ответ

1 голос
/ 26 сентября 2011

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

<xsl:stylesheet version="2.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="/*">
     <root>
      <xsl:call-template name="directDependents"/>
     </root>
 </xsl:template>

 <xsl:template name="directDependents">
  <xsl:param name="pCore" as="element()*"/>

  <xsl:variable name="vNewDependents" select=
  "/*/element
       [not(. intersect $pCore)
      and
       not(tokenize(@depends, ',')[not(. = $pCore/@name)])
       ]
  "/>

  <xsl:if test="$vNewDependents">
   <xsl:sequence select="$vNewDependents"/>
   <xsl:call-template name="directDependents">
    <xsl:with-param name="pCore" select="$pCore | $vNewDependents"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

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

<root>
    <element name="a" depends="b" />
    <element name="b" depends="c" />
    <element name="c" />
</root>

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

<root>
   <element name="c"/>
   <element name="b" depends="c"/>
   <element name="a" depends="b"/>
</root>

Обновление : Вот еще «XSLT 2.0 ищет решение» (не проверено - исправит все ошибки, когда я вернусь домой):

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

 <xsl:template match="/*">
     <root>
      <xsl:sequence select="my:directDependents(/..)"/>
     </root>
 </xsl:template>

 <xsl:function name="my:directDependents">
  <xsl:param name="pCore" as="element()*"/>

  <xsl:sequence select=
  "for $vNewDependents in
    /*/element
           [not(. intersect $pCore)
          and
           not(tokenize(@depends, ',')[not(. = $pCore/@name)])
           ]
    return
      if($vNewDependents)
        then
         (
          $vNewDependents,
          my:directDependents($pCore | $vNewDependents)
          )
        else ()
  "/>
 </xsl:function>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...