使用xslt递归转换xml文档

时间:2012-06-01 11:17:17

标签: xml xslt

我开始使用xml和xslt,我还阅读了一些教程等等。根据我的理解这个xml:

<?xml version="1.0"?>  
<Menu>  
    <Accounts type="menu" label="Accounts">  
        <ListUsers type="cmd" label="List users">  
            <cmd>HAha</cmd>  
        </ListUsers>  
        <AddUsers type="cmd" label="Add users">  
            <cmd></cmd>  
        </AddUsers>  
        <DeleteUsers type="cmd" label="Delete users">  
            <cmd></cmd>  
        </DeleteUsers>  
    </Accounts>  
    <Hardware type="menu" label="Hardware">  
        <ListDisks type="cmd" label="List disks">  
            <cmd></cmd>  
        </ListDisks>  
    </Hardware>  
    <Network type="menu" label="Network"></Network>  
    <Filesystem type="menu" label="Filesystem"></Filesystem>  
</Menu>

和这个xslt:

<?xml version="1.0"?>  
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
<xsl:template match="/*">   
    <xsl:apply-templates select="*"/>  
</xsl:template>  
<xsl:template match="*">  
    <div><xsl:value-of select="@label"/></div>  
</xsl:template>   
</xsl:stylesheet>

应该输出所有元素的标签,但它没有...我错过了什么,请你纠正并解释我,谢谢。

2 个答案:

答案 0 :(得分:4)

那么你应该向我们展示你想要的输出,但是如果你想要处理所有元素,那么确保你为所有元素保持活着处理,或者通过更改

来平整层次结构
<xsl:template match="/*">
<xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="/*">
<xsl:apply-templates select=".//*"/>
</xsl:template>

或通过更改

使用递归
<xsl:template match="*">
<div><xsl:value-of select="@label"/></div>
</xsl:template>

类似

<xsl:template match="*">
<div>
  <xsl:value-of select="@label"/>
  <xsl:apply-templates select="*"/>
</div>
</xsl:template>

答案 1 :(得分:1)

此代码有两个问题

<xsl:template match="*">       
  <div>
    <xsl:value-of select="@label"/>
  </div>   
</xsl:template>
  1. 不是顶级元素(或顶部元素本身)子元素的元素处理。要更正此问题,应将新指令附加到模板正文 - 例如:<xsl:apply-templates select="*"/>

  2. 没有label属性的元素会生成空<div>如果使用了正确的模板匹配模式,则可以避免这种情况仅为具有此属性的元素选择模板。

  3. 这是一个完整的解决方案,它可以像一样简单明了:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="*[@label]">
         <div><xsl:value-of select="@label"/></div>
       <xsl:apply-templates select="*"/>
     </xsl:template>
     <xsl:template match="text()"/>
    </xsl:stylesheet>
    

    在提供的XML文档上应用此转换时:

    <Menu>
        <Accounts type="menu" label="Accounts">
            <ListUsers type="cmd" label="List users">
                <cmd>HAha</cmd>
            </ListUsers>
            <AddUsers type="cmd" label="Add users">
                <cmd></cmd>
            </AddUsers>
            <DeleteUsers type="cmd" label="Delete users">
                <cmd></cmd>
            </DeleteUsers>
        </Accounts>
        <Hardware type="menu" label="Hardware">
            <ListDisks type="cmd" label="List disks">
                <cmd></cmd>
            </ListDisks>
        </Hardware>
        <Network type="menu" label="Network"></Network>
        <Filesystem type="menu" label="Filesystem"></Filesystem>
    </Menu>
    

    产生了想要的正确结果:

    <div>Accounts</div>
    <div>List users</div>
    <div>Add users</div>
    <div>Delete users</div>
    <div>Hardware</div>
    <div>List disks</div>
    <div>Network</div>
    <div>Filesystem</div>