如何在儿童中订购具有依赖性的元素

时间:2014-07-04 09:47:40

标签: xslt xslt-2.0

我想根据其他元素的子元素中的依赖关系将处理顺序更改为元素列表。

简化示例XML:

<root>
  <elem name="a">
    <dependency name="b"/>
    <dependency name="c"/>
  </elem>
  <elem name="b">
    <dependency name="x"/>
    <dependency name="d"/>
  </elem>
  <elem name="c">
    <dependency name="e"/>
  </elem>
  <elem name="d">
    <dependency name="y"/>
    <dependency name="e"/>
  </elem>
  <elem name="e">
    <dependency name="x"/>
  </elem>
</root>

我想要处理它们的顺序如下:

<root>
  <elem name="e">
    <dependency name="x"/>
  <elem name="c">
    <dependency name="e"/>
  </elem>
  <elem name="d">
    <dependency name="y"/>
    <dependency name="e"/>
  </elem>
  <elem name="b">
    <dependency name="x"/>
    <dependency name="d"/>
  </elem>
  <elem name="a">
    <dependency name="b"/>
    <dependency name="c"/>
  </elem>
</root>

依赖于c的元素de的顺序并不重要。文档顺序很好,但排序也可以。 在排序中可以忽略任何没有elem元素的依赖项,例如xy

我一直在尝试几个似乎做类似事情的示例样式表,但我没有成功。自从我上次使用XSLT(不幸的是)已经有一段时间了,现在我有点坚持这个。一点点的帮助将不胜感激。我没有要求提供完整的样式表,但我会非常感谢能够让我朝着正确方向前进的片段。

1 个答案:

答案 0 :(得分:1)

我编写了一个函数,它试图根据依赖项收集elem元素:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="mf">

<xsl:output indent="yes"/>

<xsl:key name="name" match="elem" use="@name"/>

<xsl:key name="dep" match="elem" use="dependency/@name[key('name', .)]"/>

<xsl:variable name="main-doc" select="/"/>

<xsl:variable name="all-elements" select="root/elem"/>

<xsl:function name="mf:collect" as="element(elem)*">
  <xsl:param name="elements-of-level" as="element(elem)*"/>
  <xsl:param name="collected-elements" as="element(elem)*"/>
  <xsl:variable name="deps" 
     select="key('dep', $elements-of-level/@name, $main-doc)
                [not(. intersect $collected-elements) 
                 and not(dependency/@name = ($all-elements except ($elements-of-level, $collected-elements))/@name)]"/>
  <xsl:sequence select="if (not($deps)) then $collected-elements
                        else mf:collect($deps, ($collected-elements, $deps))"/>
</xsl:function>

<xsl:template match="root">
  <xsl:copy>
    <xsl:variable name="start" select="elem[not(dependency/@name = //elem/@name)]"/>
    <xsl:sequence select="mf:collect($start, $start)"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

输入

<root>
  <elem name="a">
    <dependency name="b"/>
    <dependency name="c"/>
  </elem>
  <elem name="b">
    <dependency name="x"/>
    <dependency name="d"/>
  </elem>
  <elem name="c">
    <dependency name="e"/>
  </elem>
  <elem name="d">
    <dependency name="y"/>
    <dependency name="e"/>
  </elem>
  <elem name="e">
    <dependency name="x"/>
  </elem>
</root>

Saxon 9.5给我输出

<root>
   <elem name="e">
      <dependency name="x"/>
  </elem>
   <elem name="c">
      <dependency name="e"/>
  </elem>
   <elem name="d">
      <dependency name="y"/>
      <dependency name="e"/>
  </elem>
   <elem name="b">
      <dependency name="x"/>
      <dependency name="d"/>
  </elem>
   <elem name="a">
      <dependency name="b"/>
      <dependency name="c"/>
  </elem>
</root>