2010-08-02 246 views
2

樹導航我有這樣的樹結構化的XML(toc.xml文件):使用XML和XSLT

<?xml version="1.0" encoding="utf-8"?> 
<toc> 
    <item name="top" key="4294967296" subkey="1"> 
    <item name="child1" key="4294967611" subkey=""> 
     <item name="child2-1" key="4294961611" subkey=""> 
     <item name="child3-1" key="4294967613" subkey=""/> 
     <item name="child3-2" key="4294967612" subkey=""/> 
     </item> 
     <item name="child2-2" key="4294962611" subkey=""> 
     <item name="d" key="4294974806" subkey=""/> 
     </item> 
     <item name="child2-3" key="4294963611" subkey=""> 
     <item name="d" key="4294967661" subkey=""/> 
     <item name="PI" key="4294967659" subkey=""/> 
     <item name="q" key="4294967660" subkey=""/> 
     </item> 
     <item name="child2-4" key="4294964611" subkey=""/> 
     <item name="child2-5" key="4294965611" subkey=""> 
     <item name="bb" key="4294967616" subkey=""/> 
     <item name="bb" key="4294967620" subkey=""/> 
     <item name="f" key="4294967615" subkey=""/> 
     </item> 
    </item> 
    </item> 
</toc> 

每個關鍵是在文檔中是唯一的。

我有進口的TOC XML,並試圖輸出導航的XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="html" indent="no" /> 
    <xsl:variable name="id" select="/member/@id" /> 

    <xsl:template match="/member"> 
    <html> 
     <head> 
     <title><xsl:value-of select="/member/name"/></title> 
     </head> 
     <body> 
     <div class="navigation"> 
      <xsl:apply-templates select="document('toc.xml')" /> 
     </div> 
     <div class="content"> 
      <xsl:apply-templates /> 
     </div> 
     </body> 
    </html> 
    </xsl:template> 
</xsl> 

,想找到HTML文件中的一個節點,並輸出以下HTML:

...html... 
<div class="navigation"> 
    <ul> 
    <li><a href="#">top</a><ul> 
     <li><a href="#">child1</li><ul> 
     <li><a href="#">child2</li><ul> 
      <li><a href="#">child3-1</a></li> 
      <li><a href="#">child3-2</a></li> 
      </ul></li> 
     </ul></li> 
     </ul></li> 
    </ul> 
</div> 
...more html... 

基本上我想搜索一個節點:item [@key ='4294967611']並輸出所有父節點和直接子節點。

我覺得這應該很容易,但我很努力地找到有關如何做到這一點的信息。我的XSLT知識不是很好。

+0

在您輸入的child2中會出現多次不同的孩子(例如bb)在你的輸出中。這是一個副本錯誤? child2是否是獨一無二的? – p00ya 2010-08-02 08:07:30

+0

對不起,是的,child2被輸入以指示深度,但名稱是唯一的。我會更新這個問題。 – 2010-08-02 08:13:16

+0

您是否打算將密鑰作爲參數傳遞給xslt? – 2010-08-02 09:57:57

回答

3

隨着所提供的輸入(有沒有獨特@key),這個樣式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:param name="key" select="4294967611"/> 
    <xsl:template match="item"> 
     <xsl:choose> 
      <xsl:when test="generate-id() = 
          generate-id(../item[@key=$key][1]) 
          and 
          not(item[@key=$key])"> 
       <xsl:call-template name="chain"> 
        <xsl:with-param name="parents" select="ancestor-or-self::item"/> 
        <xsl:with-param name="childs" select="item"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:apply-templates/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
    <xsl:template name="chain"> 
     <xsl:param name="parents"/> 
     <xsl:param name="childs"/> 
     <xsl:if test="$parents"> 
      <ul> 
       <li> 
        <a href="#"> 
         <xsl:value-of select="$parents[1]/@name"/> 
        </a> 
        <xsl:call-template name="chain"> 
         <xsl:with-param name="parents" select="$parents[position()!=1]"/> 
         <xsl:with-param name="childs" select="$childs"/> 
        </xsl:call-template> 
        <xsl:if test="count($parents)=1"> 
         <ul> 
          <xsl:for-each select="$childs"> 
           <li> 
            <a href="#"> 
             <xsl:value-of select="@name"/> 
            </a> 
           </li> 
          </xsl:for-each> 
         </ul> 
        </xsl:if> 
       </li> 
      </ul> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

輸出:

<ul> 
    <li> 
     <a href="#">top</a> 
     <ul> 
      <li> 
       <a href="#">child1</a> 
       <ul> 
        <li> 
         <a href="#">child2-1</a> 
         <ul> 
          <li> 
           <a href="#">child3-1</a> 
          </li> 
          <li> 
           <a href="#">child3-2</a> 
          </li> 
         </ul> 
        </li> 
       </ul> 
      </li> 
     </ul> 
    </li> 
</ul> 

如果@key是獨一無二的,這個樣式表應該工作:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="itemBykey" match="item" use="@key"/> 
    <xsl:param name="key" select="4294967611"/> 
    <xsl:template match="/"> 
     <xsl:for-each select="key('itemBykey',$key)"> 
      <xsl:call-template name="chain"> 
       <xsl:with-param name="parents" select="ancestor-or-self::item"/> 
       <xsl:with-param name="childs" select="item"/> 
      </xsl:call-template> 
     </xsl:for-each> 
    </xsl:template> 
    <xsl:template name="chain"> 
     <xsl:param name="parents"/> 
     <xsl:param name="childs"/> 
     <xsl:if test="$parents"> 
      <ul> 
       <li> 
        <a href="#"> 
         <xsl:value-of select="$parents[1]/@name"/> 
        </a> 
        <xsl:call-template name="chain"> 
         <xsl:with-param name="parents" select="$parents[position()!=1]"/> 
         <xsl:with-param name="childs" select="$childs"/> 
        </xsl:call-template> 
        <xsl:if test="count($parents)=1"> 
         <ul> 
          <xsl:for-each select="$childs"> 
           <li> 
            <a href="#"> 
             <xsl:value-of select="@name"/> 
            </a> 
           </li> 
          </xsl:for-each> 
         </ul> 
        </xsl:if> 
       </li> 
      </ul> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 
+0

嗨,謝謝你。獨特的鑰匙就像魅力一樣。你會如何將子鍵添加到「select =」鍵('itemBykey',$ key)「? – 2010-08-02 15:36:14

+1

@Barry Jones:你很好,關於你的問題:現在鍵是@key和@subkey,因此xsl:key/@ use應該是'concat(@ key,'some-character-not-present-in-keys',@ subkey)'','key()'函數應該像'key(' itemBykey',concat($ key,'some-character-not-present-in-keys',$ subkey))'with $ subkey has a new param added。 – 2010-08-02 15:51:40

+0

抱歉再次提問,但在這裏遇到了一些麻煩。 我用: 鍵(「itemByKey」,CONCAT($鍵,「 - 」,$子項) 但只是不工作,甚至當我使用它的選擇和關鍵defenition兩個: 的 並選擇: ) 其中$ id和$ subId聲明爲: 2010-08-03 14:22:06

-1

這將生成所需輸出:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="item"> 
    <ul> 
     <li> 
     <a href="'#'"> 
      <xsl:value-of select="@name"/> 
     </a> 
     <xsl:apply-templates select="*"/> 
    </li> 
    </ul> 
</xsl:template> 
</xsl:stylesheet> 

取而代之的是「#」 HREF你應該保存的URL一樣的name屬性的XML文件。要找到一個節點,您需要將搜索作爲參數傳遞給您。如何做到這一點取決於你如何做轉型。

+0

Andreas,您的xslt正在生成超過所需的更多ul標籤。葉節點應該屬於單個ul標籤。例如。 child3-1和child3-2應該屬於單獨的li標籤,應該在單個ul標籤下分組 – 2010-08-02 09:53:31

0

這是使用ulli元素的正確父級子級別的正確實施。它只會輸出那些父母的節點,或者是在xsl:variable keyVar中給出的鍵值的直接子節點。

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" > 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:variable name ="keyVar" select="'4294967666'" /> 

    <xsl:template match="toc"> 
    <ul> 
     <xsl:apply-templates select="item" /> 
    </ul> 
    </xsl:template> 

    <xsl:template match="item"> 
    <li> 
     <a href="#" /> 
     <xsl:value-of select="@name"/> 
     <xsl:if test ="count(descendant::item) > 0"> 
     <ul> 
      <xsl:apply-templates select="item[.//@key=$keyVar or ../@key = $keyVar]" /> 
     </ul> 
     </xsl:if> 
    </li> 

    </xsl:template> 
</xsl:stylesheet> 

輸出層次結構:

<?xml version="1.0" encoding="utf-8"?> 
<ul> 
    <li>top<ul> 
    <li>child1<ul> 
     <li>child2-1<ul> 
     <li>child3-1</li> 
     <li>child3-2</li> 
     </ul></li> 
     <li>child2-2<ul> 
     <li>d</li> 
     </ul></li> 
     <li>child2-3<ul> 
     <li>d</li> 
     <li>PI</li> 
     <li>q</li> 
     </ul></li> 
     <li>child2-4</li> 
     <li>child2-5<ul> 
     <li>bb</li> 
     <li>bb</li> 
     <li>f</li> 
     </ul></li> 
    </ul></li> 
    </ul></li> 
</ul> 
+0

嘿,謝謝你。通過直接的孩子,我的意思只是直接在選定節點下的層次。所以如果選擇了child-1,它只會顯示child2-1,child2-2等。此外,這似乎輸出每個頂級項目,即/ toc /項目 – 2010-08-02 12:03:58

0

首先,所提供的想要的輸出不能很好地形成的XML文檔或片段。

另外,在提供的源XML文檔中沒有<item name="child2" ...>元素。

此外,有六個item元素與key='4294967611',所以這也不是一個可用於標識元素的標準。

我想,你要想這

<ul> 
    <li><a href="#">top</a> 
     <ul> 
     <li><a href="#">child1</a> 
     <ul> 
      <li><a href="#">child2-1</a> 
       <ul> 
        <li><a href="#">child3-1</a></li> 
        <li><a href="#">child3-2</a></li> 
       </ul> 
      </li> 
     </ul> 
     </li> 
     </ul> 
    </li> 
</ul> 

如果我猜測是正確的,這裏是一個可能的解決方案:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:param name="pEl" select="//item[@name='child2-1']"/> 

<xsl:template match="toc"> 
    <xsl:variable name="pChain" select="$pEl/ancestor-or-self::item"/> 
    <xsl:apply-templates select="$pChain[1]"> 
    <xsl:with-param name="pChain" select="$pChain"/> 
    <xsl:with-param name="pEndElementId" select="generate-id($pEl)"/> 
    </xsl:apply-templates> 
</xsl:template> 

<xsl:template match="item"> 
    <xsl:param name="pChain" select="/.."/> 
    <xsl:param name="pcurPosition" select="1"/> 
    <xsl:param name="pEndElementId"/> 
    <ul> 
     <li><a href="#"><xsl:value-of select="@name"/></a> 
     <xsl:choose> 
     <xsl:when test="generate-id() = $pEndElementId"> 
      <ul> 
      <xsl:apply-templates select="item" mode="leafChildren"/> 
      </ul> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:apply-templates select="$pChain[position()=$pcurPosition+1]"> 
      <xsl:with-param name="pChain" select="$pChain"/> 
      <xsl:with-param name="pcurPosition" select="$pcurPosition +1"/> 
      <xsl:with-param name="pEndElementId" select="$pEndElementId"/> 
      </xsl:apply-templates> 
     </xsl:otherwise> 
     </xsl:choose> 
     </li> 
    </ul> 
</xsl:template> 

<xsl:template match="item" mode="leafChildren"> 
    <li><a href="#"><xsl:value-of select="@name"/></a></li> 
</xsl:template> 
</xsl:stylesheet> 

當這種轉化應用上提供的XML文檔

<toc> 
<item name="top" key="4294967296" subkey="1"> 
    <item name="child1" key="4294967611" subkey=""> 
     <item name="child2-1" key="4294967611" subkey=""> 
      <item name="child3-1" key="4294967613" subkey=""/> 
      <item name="child3-2" key="4294967612" subkey=""/> 
     </item> 
     <item name="child2-2" key="4294967611" subkey=""> 
      <item name="d" key="4294974806" subkey=""/> 
     </item> 
     <item name="child2-3" key="4294967611" subkey=""> 
      <item name="d" key="4294967661" subkey=""/> 
      <item name="PI" key="4294967659" subkey=""/> 
      <item name="q" key="4294967660" subkey=""/> 
     </item> 
     <item name="child2-4" key="4294967611" subkey=""/> 
     <item name="child2-5" key="4294967611" subkey=""> 
      <item name="bb" key="4294967616" subkey=""/> 
      <item name="bb" key="4294967620" subkey=""/> 
      <item name="f" key="4294967615" subkey=""/> 
     </item> 
    </item> 
</item> 
</toc> 

想要的結果產生

<ul> 
    <li> 
     <a href="#">top</a> 
     <ul> 
     <li> 
      <a href="#">child1</a> 
      <ul> 
       <li> 
        <a href="#">child2-1</a> 
        <ul> 
        <li> 
         <a href="#">child3-1</a> 
        </li> 
        <li> 
         <a href="#">child3-2</a> 
        </li> 
        </ul> 
       </li> 
      </ul> 
     </li> 
     </ul> 
    </li> 
</ul> 

如果我對通緝的結果的猜測是不是一擊,請,糾正你的問題,並提供了一個結構良好的輸出。