0

私はフラットな xml 構造を持っています。階層に変換する必要があります。stackoverflow の助けを借りて、私はそれを行うことができました。質問: 同じフラット構造を使用して 1 つのブランチのみを表示することは可能ですか?

これが私のxmlファイルとxslファイルです:

XML

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="Stack.xsl"?>
<Items>
    <Item>
        <Id>1</Id>
        <ParentId>0</ParentId>
        <Name>1</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>2</Id>
        <ParentId>1</ParentId>
        <Name>1.1</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>3</Id>
        <ParentId>1</ParentId>
        <Name>1.2</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>4</Id>
        <ParentId>1</ParentId>
        <Name>1.3</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>5</Id>
        <ParentId>1</ParentId>
        <Name>1.4</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>6</Id>
        <ParentId>0</ParentId>
        <Name>2</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>7</Id>
        <ParentId>6</ParentId>
        <Name>2.1</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>8</Id>
        <ParentId>6</ParentId>
        <Name>2.2</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>9</Id>
        <ParentId>0</ParentId>
        <Name>3</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>10</Id>
        <ParentId>3</ParentId>
        <Name>1.2.1</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>11</Id>
        <ParentId>8</ParentId>
        <Name>2.2.1</Name>
        <SortOrder>0</SortOrder>
    </Item>
    <Item>
        <Id>11</Id>
        <ParentId>5</ParentId>
        <Name>1.4.1</Name>
        <SortOrder>0</SortOrder>
    </Item>
</Items>

XSL

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml">

    <xsl:param name="SelectedId" select="'10'"/>
    <xsl:key name="ChildNodes" match="/Items/Item" use="ParentId"/>

    <xsl:template match="Items">
        <ul>
          <xsl:apply-templates select="Item[ParentId = 0]" />
        </ul>
    </xsl:template>

    <xsl:template match="Item">
        <li>
            <xsl:choose>
                <xsl:when test="Id = $SelectedId">
                    <b><xsl:value-of select="Name" /></b>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="Name" />
                </xsl:otherwise>
            </xsl:choose>

            <xsl:variable name="Descendants" select="key ('ChildNodes', Id)" />

            <xsl:if test="count ($Descendants) > 0">
                <ul>
                    <xsl:apply-templates select="$Descendants" />
                </ul>
            </xsl:if>
        </li>
    </xsl:template>
</xsl:stylesheet>

私が持っている現在の出力:

1
   1.1
   1.2
        1.2.1
   1.3
   1.4
        1.4.1
2
   2.1
   2.2
        2.2.1
3

望ましい結果の例:

1
   1.1
   1.2
        1.2.1
   1.3
   1.4
2
3
4

1 に答える 1

1

これを行う 1 つの方法は、ノード セット関数を利用することです。これには、XSLT で拡張名前空間を使用する必要があります。

あなたができることは、現在のようにDescendants変数を直接出力する代わりに:

<ul>
   <xsl:apply-templates select="$Descendants"/>
</ul>

代わりに、結果を変数に格納します

<xsl:variable name="list">
   <ul>
      <xsl:apply-templates select="$Descendants"/>
   </ul>
</xsl:variable>

次に、この「結果ツリーのフラグメント」をノードセットに変換できます。これにより、選択した要素 ( b要素に保持されている) が存在するかどうかを確認できます。もしそうなら、あなたはそれを出力することができます

<xsl:if test="exsl:node-set($list)//li[b]">
   <xsl:copy-of select="$list"/>
</xsl:if>

ここに完全な XSLT があります

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:exsl="urn:schemas-microsoft-com:xslt" 
 exclude-result-prefixes="exsl">
   <xsl:output method="html"/>
   <xsl:param name="SelectedId" select="'10'"/>
   <xsl:key name="ChildNodes" match="/Items/Item" use="ParentId"/>

   <xsl:template match="Items">
      <ul>
         <xsl:apply-templates select="Item[ParentId = 0]"/>
      </ul>
   </xsl:template>

   <xsl:template match="Item">
      <li>
         <xsl:choose>
            <xsl:when test="Id = $SelectedId">
               <b>
                  <xsl:value-of select="Name"/>
               </b>
            </xsl:when>
            <xsl:otherwise>
               <xsl:value-of select="Name"/>
            </xsl:otherwise>
         </xsl:choose>
         <xsl:variable name="Descendants" select="key ('ChildNodes', Id)"/>
         <xsl:if test="count ($Descendants) &gt; 0">
            <xsl:variable name="list">
               <ul>
                  <xsl:apply-templates select="$Descendants"/>
               </ul>
            </xsl:variable>
            <xsl:if test="exsl:node-set($list)//li[b]">
               <xsl:copy-of select="$list"/>
            </xsl:if>
         </xsl:if>
      </li>
   </xsl:template>
</xsl:stylesheet>

サンプル XML に適用すると、次のように出力されます。

<ul>
   <li>1
      <ul>
         <li>1.1</li>
         <li>1.2
            <ul>
               <li>
                  <b>1.2.1</b>
               </li>
            </ul></li>
         <li>1.3</li>
         <li>1.4</li>
      </ul></li>
   <li>2</li>
   <li>3</li>
</ul>

ここでは Microsoft XML を使用しているため、拡張子の名前空間は "urn:schemas-microsoft-com:xslt" です。他のプロセッサについては、おそらく「http://exslt.org/common」を使用する必要があります。

于 2012-08-29T12:15:09.263 に答える