简单的情况……对于任何随机的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()),'/')),'
')