2

我有以下 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>

这表示如下结构:

    • 巴兹
      • 沃尔多
    • 曲克斯
      • 沃尔多
    • 沃尔多
  • 酒吧
    • 巴兹
      • 沃尔多
    • 曲克斯
      • 沃尔多
    • 沃尔多

实际的 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!

4

1 回答 1

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. 第二遍是一个身份规则,由一个带有空主体的模板(“删除”模板)覆盖,用于不包含带有 string-value的thingwith 属性的子树。name"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>

第二遍去除两个<thing name="Baz" available="yes"/>元素以产生最终结果。

于 2012-08-13T13:49:50.360 回答