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」を含む「branchs」のみを含む結果を生成します。

<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パス変換です。

  2. 最初のパスは、親子関係が明示的に表現されるツリーを構築します。

  3. 2番目のパスはIDルールであり、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>

2番目のパスは、2つの<thing name="Baz" available="yes"/>要素を取り除き、最終結果を生成します。

于 2012-08-13T13:49:50.360 に答える