简单的情况……对于任何随机的XML文件,我想创建一个包含它的每个节点的列表,但没有任何重复!所以类似于:
- <root name="example">
- <child id="1">
- <grandchild/>
- </child>
- <child id="2"/>
- <child id="3"/>
- </root>
被翻译成:
- /root
- /root/@name
- /root/child
- /root/child/@id
- /root/child/grandchild
如何通过使用XSLT来做到这一点?
只是为了好玩,没有扩展功能.
- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:template match="text()"/>
- <xsl:template match="*|@*">
- <xsl:param name="pPath"/>
- <xsl:param name="pNames" select="'
'"/>
- <xsl:variable name="vPath"
- select="concat($pPath,'/',substring('@',1 div (count(.|../@*) =
- count(../@*))),name())"/>
- <xsl:variable name="vNames">
- <xsl:if test="not(contains($pNames,concat('
',$vPath,'
')))">
- <xsl:value-of select="concat($vPath,'
')"/>
- </xsl:if>
- <xsl:apply-templates select="*[1]|@*">
- <xsl:with-param name="pPath" select="$vPath"/>
- <xsl:with-param name="pNames" select="$pNames"/>
- </xsl:apply-templates>
- </xsl:variable>
- <xsl:value-of select="$vNames"/>
- <xsl:apply-templates select="following-sibling::*[1]">
- <xsl:with-param name="pPath" select="$pPath"/>
- <xsl:with-param name="pNames" select="concat($pNames,$vNames)"/>
- </xsl:apply-templates>
- </xsl:template>
- </xsl:stylesheet>
输出:
- /root
- /root/@name
- /root/child
- /root/child/@id
- /root/child/grandchild
编辑:XSLT / XPath 2.0的更好示例.这个XPath 2.0行:
- string-join(
- distinct-values(
- (//*|//@*)
- /string-join(
- (ancestor::node()/name(),if (self::attribute())
- then concat('@',name())
- else name()),'/')),'
')