2010-08-02 231 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> 

如果我对通缉的结果的猜测是不是一击,请,纠正你的问题,并提供了一个结构良好的输出。