此XSLT转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:strip-space elements="*"/> <xsl:variable name="vApos">'</xsl:variable> <xsl:template match="*[@* or not(*)] "> <xsl:if test="not(*)"> <xsl:apply-templates select="ancestor-or-self::*" mode="path"/> <xsl:value-of select="concat('=',$vApos,.,$vApos)"/> <xsl:text>
</xsl:text> </xsl:if> <xsl:apply-templates select="@*|*"/> </xsl:template> <xsl:template match="*" mode="path"> <xsl:value-of select="concat('/',name())"/> <xsl:variable name="vnumPrecSiblings" select= "count(preceding-sibling::*[name()=name(current())])"/> <xsl:if test="$vnumPrecSiblings"> <xsl:value-of select="concat('[', $vnumPrecSiblings +1, ']')"/> </xsl:if> </xsl:template> <xsl:template match="@*"> <xsl:apply-templates select="../ancestor-or-self::*" mode="path"/> <xsl:value-of select="concat('[@',name(), '=',$vApos,.,$vApos,']')"/> <xsl:text>
</xsl:text> </xsl:template></xsl:stylesheet>
当应用于提供的XML文档时:
<root> <elemA>one</elemA> <elemA attribute1='first' attribute2='second'>two</elemA> <elemB>three</elemB> <elemA>four</elemA> <elemC> <elemB>five</elemB> </elemC></root>
产生完全想要的正确结果:
/root/elemA='one'/root/elemA[2]='two'/root/elemA[2][@attribute1='first']/root/elemA[2][@attribute2='second']/root/elemB='three'/root/elemA[3]='four'/root/elemC/elemB='five'
当通过@ c0mrade应用于新提供的文档时:
<root> <elemX serial="kefw90234kf2esda9231"> <id>89734</id> </elemX></root>
再次产生正确的结果:
/root/elemX='89734'/root/elemX[@serial='kefw90234kf2esda9231']
说明:
- 仅对没有子元素或具有属性的元素进行匹配和处理。
- 对于任何此类元素,如果它没有子元素,则其所有祖先或自身元素都以命名为的特定模式进行处理’
path
‘。然后”=’thevalue
‘“输出零件,然后输出NL字符。 - 然后处理匹配元素的所有属性。
- 最后,将模板应用于所有子元素。
- 在’
path
‘模式下处理元素很简单:输出一个/字符和元素名称。然后,如果前面有同名的同级兄弟,则输出“[numPrecSiblings + 1]
”部分。 - 属性的处理很简单:首先
ancestor-or-self::
以'path'
模式处理其父元素的所有元素,然后输出[attrName = attrValue]
部分,然后输出NL字符。
注意事项:
- 命名空间中的名称以其初始可读形式显示,没有任何问题。
- 为提高可读性,[1]从不显示索引。
以下是我的初步答案(可以忽略)
这是一个纯XSLT 1.0解决方案:
以下是一个示例xml文档和一个样式表,该样式表带有一个节点集参数,并为每个成员节点生成一个有效的XPath表达式。
stylesheet (buildPath.xsl):
<xsl:stylesheet version='1.0'xmlns:xsl='http://www.w3.org/1999/XSL/Transform'xmlns:msxsl="urn:schemas-microsoft-com:xslt" ><xsl:output method="text"/><xsl:variable name="theParmNodes" select="//namespace::*[local-name() ='myNamespace']"/><xsl:template match="/"> <xsl:variable name="theResult"> <xsl:for-each select="$theParmNodes"> <xsl:variable name="theNode" select="."/> <xsl:for-each select="$theNode |$theNode/ancestor-or-self::node()[..]"> <xsl:element name="slash">/</xsl:element> <xsl:choose> <xsl:when test="self::*"> <xsl:element name="nodeName"> <xsl:value-of select="name()"/> <xsl:variable name="thisPosition" select="count(preceding-sibling::*[name(current()) = name()])"/> <xsl:variable name="numFollowing" select="count(following-sibling::*[name(current()) = name()])"/> <xsl:if test="$thisPosition + $numFollowing > 0"> <xsl:value-of select="concat('[', $thisPosition + 1, ']')"/> </xsl:if> </xsl:element> </xsl:when> <xsl:otherwise> <!-- This node is not an element --> <xsl:choose> <xsl:when test="count(. | ../@*) = count(../@*)"> <!-- Attribute --> <xsl:element name="nodeName"> <xsl:value-of select="concat('@',name())"/> </xsl:element> </xsl:when> <xsl:when test="self::text()"> <!-- Text --> <xsl:element name="nodeName"> <xsl:value-of select="'text()'"/> <xsl:variable name="thisPosition" select="count(preceding-sibling::text())"/> <xsl:variable name="numFollowing" select="count(following-sibling::text())"/> <xsl:if test="$thisPosition + $numFollowing > 0"> <xsl:value-of select="concat('[', $thisPosition + 1, ']')"/> </xsl:if> </xsl:element> </xsl:when> <xsl:when test="self::processing-instruction()"> <!-- Processing Instruction --> <xsl:element name="nodeName"> <xsl:value-of select="'processing-instruction()'"/> <xsl:variable name="thisPosition" select="count(preceding-sibling::processing-instruction())"/> <xsl:variable name="numFollowing" select="count(following-sibling::processing-instruction())"/> <xsl:if test="$thisPosition + $numFollowing > 0"> <xsl:value-of select="concat('[', $thisPosition + 1, ']')"/> </xsl:if> </xsl:element> </xsl:when> <xsl:when test="self::comment()"> <!-- Comment --> <xsl:element name="nodeName"> <xsl:value-of select="'comment()'"/> <xsl:variable name="thisPosition" select="count(preceding-sibling::comment())"/> <xsl:variable name="numFollowing" select="count(following-sibling::comment())"/> <xsl:if test="$thisPosition + $numFollowing > 0"> <xsl:value-of select="concat('[', $thisPosition + 1, ']')"/> </xsl:if> </xsl:element> </xsl:when> <!-- Namespace: --> <xsl:when test="count(. | ../namespace::*) = count(../namespace::*)"> <xsl:variable name="apos">'</xsl:variable> <xsl:element name="nodeName"> <xsl:value-of select="concat('namespace::*', '[local-name() = ', $apos, local-name(), $apos, ']')"/> </xsl:element> </xsl:when> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:for-each> <xsl:text>
</xsl:text> </xsl:for-each> </xsl:variable> <xsl:value-of select="msxsl:node-set($theResult)"/></xsl:template></xsl:stylesheet>
xml source (buildPath.xml):
<!-- top level Comment --><root> <nodeA>textA</nodeA> <nodeA id="nodeA-2"> <?myProc ?> xxxxxxxx <nodeB/> <nodeB xmlns:myNamespace="myTestNamespace"> <!-- Comment within /root/nodeA[2]/nodeB[2] --> <nodeC/> <!-- 2nd Comment within /root/nodeA[2]/nodeB[2] --> </nodeB> yyyyyyy <nodeB/> <?myProc2 ?> </nodeA></root><!-- top level Comment -->
结果:
/root/nodeA[2]/nodeB[2]/namespace::*[local-name() = 'myNamespace']/root/nodeA[2]/nodeB[2]/nodeC/namespace::*[local-name() ='myNamespace']
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)