XSLT 1.0:向后移动和过滤树

时间:2012-08-13 13:13:19

标签: xslt tree xslt-1.0

我有以下XML:

<things>
  <thing name="Foo" available="yes"/>
  <thing name="Bar" available="no"/>
  <thing name="Baz" available="yes">
    <parent name="Foo"/>
    <parent name="Bar"/>
  </thing>
  <thing name="Qux" available="no">
    <parent name="Foo"/>
    <parent name="Bar"/>
  </thing>
  <thing name="Waldo" available="yes">
    <parent name="Foo"/>
    <parent name="Bar"/>
    <parent name="Baz"/>
    <parent name="Qux"/>
  </thing>
</things>

这表示如下结构:

    • 巴兹
      • 沃尔多
    • Qux
      • 沃尔多
    • 沃尔多
  • 酒吧
    • 巴兹
      • 沃尔多
    • Qux
      • 沃尔多
    • 沃尔多

实际的XML非常大,嵌套很深。无法实现的东西可以在任何地方。没有循环(自己作为祖先的东西)。

现在我想生成所有可能的Waldo路径,过滤掉包含不可用内容的路径。我正在寻找以下结果:

<ul>
  <li>
    <a href="#Foo">Foo</a>
    <ul>
      <li>
        <a href="#Baz">Baz</a>
        <ul>
          <li>
            <b>Waldo</b>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
<ul>
  <li>
    <a href="#Foo">Foo</a>
    <ul>
      <li>
        <b>Waldo</b>
      </li>
    </ul>
  </li>
</ul>

那是:

    • 巴兹
      • 沃尔多
    • 沃尔多

从叶子节点开始,查找树,生成所有可能的路径而忽略不可用的路径让我感到难过。任何见解,散文,伪代码或XSLT都非常感谢!

1 个答案:

答案 0 :(得分:1)

此转化

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

 <xsl:key name="kChildren" match="thing" use="parent/@name"/>

 <xsl:template match="/*">
   <xsl:variable name="vrtfPass1">
         <things>
           <xsl:apply-templates select="thing[not(parent)]"/>
         </things>
   </xsl:variable>


   <xsl:apply-templates select="ext:node-set($vrtfPass1)/*"
                        mode="pass2"/>
 </xsl:template>

 <xsl:template match="thing">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="key('kChildren', @name)"/>
    </xsl:copy>
 </xsl:template>

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

 <xsl:template mode="pass2"
      match="*[not(@name = 'Waldo' or .//*[@name='Waldo'])]" />
</xsl:stylesheet>

应用于提供的XML文档

<things>
    <thing name="Foo" available="yes"/>
    <thing name="Bar" available="no"/>
    <thing name="Baz" available="yes">
        <parent name="Foo"/>
        <parent name="Bar"/>
    </thing>
    <thing name="Qux" available="no">
        <parent name="Foo"/>
        <parent name="Bar"/>
    </thing>
    <thing name="Waldo" available="yes">
        <parent name="Foo"/>
        <parent name="Bar"/>
        <parent name="Qux"/>
    </thing>
</things>

生成的结果只包含“分支”,其中包含“waldo”:

<things>
   <thing name="Foo" available="yes">
      <thing name="Qux" available="no">
         <thing name="Waldo" available="yes"/>
      </thing>
      <thing name="Waldo" available="yes"/>
   </thing>
   <thing name="Bar" available="no">
      <thing name="Qux" available="no">
         <thing name="Waldo" available="yes"/>
      </thing>
      <thing name="Waldo" available="yes"/>
   </thing>
</things>

将阅读器转换为需要最终HTML格式的练习。

<强>解释

  1. 这是两次转换。

  2. 第一遍构造了一个树,其中明确表达了父子关系。

  3. 第二遍是一个身份规则,由一个带有空体(“删除”模板)的模板覆盖,用于不包含属性为thing的{​​{1}}的子树,带有字符串 - 价值name

  4. 第一遍的结果是

    "Waldo"

    第二次传递剥离两个<things> <thing name="Foo" available="yes"> <thing name="Baz" available="yes"/> <thing name="Qux" available="no"> <thing name="Waldo" available="yes"/> </thing> <thing name="Waldo" available="yes"/> </thing> <thing name="Bar" available="no"> <thing name="Baz" available="yes"/> <thing name="Qux" available="no"> <thing name="Waldo" available="yes"/> </thing> <thing name="Waldo" available="yes"/> </thing> </things> 元素以产生最终结果。