我會拉出路徑生成代碼到另一個模板,然後調入,從模板元素和屬性:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" indent="no" />
<xsl:template mode="path" match="*">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/', name())" />
<xsl:if test="count(preceding-sibling::*[name() = name(current())]) != 0">
<xsl:value-of select="concat('[',
count(preceding-sibling::*[name() = name(current())]) + 1, ']')" />
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="*">
<xsl:if test="not(*)">
<!-- this element has no children, print its path -->
<xsl:apply-templates mode="path" select="." />
<xsl:text>
</xsl:text>
</xsl:if>
<xsl:apply-templates select="@*|*" />
</xsl:template>
<xsl:template match="@*">
<!-- for an attribute, print the path to its containing element ... -->
<xsl:apply-templates mode="path" select=".." />
<!-- ... followed by "/@attributename" -->
<xsl:value-of select="concat('/@', name(), '
')" />
</xsl:template>
</xsl:stylesheet>
這是,雖然屬性節點不被認爲是他們的主元素節點的孩子XPath數據模型的方便古怪,元素是被認爲是其屬性節點的父項。
更新:處理xsi:type
要求,你就應該能夠到邏輯添加到您當前的兄弟姐妹計數代碼,區別對待類型元素。並且要在適當的位置添加值,您需要合適的value-of
。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="text" indent="no" />
<xsl:template mode="path" match="*">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/', name())" />
<!-- for typed elements, include the type in the path -->
<xsl:if test="@xsi:type">
<xsl:text>[@xsi:type = '</xsl:text>
<xsl:value-of select="@xsi:type" />
<xsl:text>']</xsl:text>
</xsl:if>
<xsl:if test="count(preceding-sibling::*[name() = name(current()) and
@xsi:type = current()/@xsi:type]) != 0">
<xsl:value-of select="concat('[',
count(preceding-sibling::*[name() = name(current()) and
@xsi:type = current()/@xsi:type]) + 1, ']')" />
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="*">
<xsl:if test="not(*)">
<!-- this element has no children, print its path -->
<xsl:apply-templates mode="path" select="." />
<xsl:text>,</xsl:text>
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
</xsl:if>
<xsl:apply-templates select="@*|*" />
</xsl:template>
<xsl:template match="@*">
<!-- for an attribute, print the path to its containing element ... -->
<xsl:apply-templates mode="path" select=".." />
<!-- ... followed by "/@attributename" -->
<xsl:value-of select="concat('/@', name(), ',', ., '
')" />
</xsl:template>
</xsl:stylesheet>
由於空節點集的字符串值是空字符串,在元素做@xsi:type = current()/@xsi:type
沒有一個xsi:type
是安全,會產生正確的結果。
你也可能要添加
<xsl:template match="@xsi:type" />
,如果你不希望生成路徑的類型的屬性。
這是這裏值得注意的是該類型的邏輯和計數是正交的 - 給
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a xsi:type="xs:string">aaa</a>
<a xsi:type="xs:integer">1</a>
<a xsi:type="xs:string">bbb</a>
<a xsi:type="xs:integer">2</a>
</root>
你會得到的
/root/a[@xsi:type = 'xs:string'],aaa
/root/a[@xsi:type = 'xs:integer'],1
/root/a[@xsi:type = 'xs:string'][2],bbb
/root/a[@xsi:type = 'xs:integer'][2],2
路徑,每個類型的計數(這是正確的,的XPath將假設正確的命名空間綁定選擇正確的事物)。
嗨伊恩, 真的很感謝你的幫助。 我需要一個增強,我覺得很棘手? 如果一個元素具有xsi:type屬性(即,是另一種類型的擴展),我需要在XPATH中的*元素名稱*中考慮這一點,而不是將其作爲屬性本身(因爲它是一個特殊/保留XSD屬性) 例如對於 我需要: /A/B [的xsi:type = 「C」]/@ ATTRIBUTE1 而不是 /a/b/@類型 它目前正在生產?這可能嗎? 謝謝! – user2992225