2016-07-27 83 views
0

要爲xml文件中的每個節點生成xpath並將此路徑作爲屬性添加到每個節點,我發現一些幫助here。 xslt文件應該如下所示:使用xslt生成xpath節點2

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes" encoding="UTF-8"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*"> 
    <xsl:copy> 
     <xsl:attribute name="xpath"> 
     <xsl:for-each select="ancestor-or-self::*"> 
      <xsl:value-of select="concat('/',local-name())"/> 
      <!--Predicate is only output when needed.--> 
      <xsl:if 
      test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]"> 
      <xsl:value-of 
       select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')" 
      /> 
      </xsl:if> 
     </xsl:for-each> 
     </xsl:attribute> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="text()"/> 

</xsl:stylesheet> 

現在我對使用xslt 2.0更緊湊的方式感興趣。例如在下面的xslt文件中,我有兩個函數createXPath和getXpath。第一個返回一個帶有節點名稱的路徑,第二個返回相應的數字。是否可以巧妙地將這些組合起來?

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:func="http://www.functx.com"> 
    <xsl:output method="xml" encoding="utf-8"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:attribute name="xpath"> 
      <xsl:value-of select="func:getXpath(.)"/> 
     </xsl:attribute> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

    <xsl:function name="func:createXPath" > 
    <xsl:param name="pNode" as="node()"/> 
    <xsl:value-of select="$pNode/ancestor-or-self::*/local-name()" separator="/"/> 
    </xsl:function> 

    <xsl:function name="func:getXpath"> 
    <xsl:param name="pNode" as="node()"/> 
    <xsl:value-of select="$pNode/ancestor-or-self::*/(count(preceding-sibling::*) + 1)" separator="/" /> 
</xsl:function> 

</xsl:stylesheet> 

回答

1

結合使用這兩種功能是相當微不足道的 - 例如,你可以做:

<xsl:function name="func:path" > 
    <xsl:param name="target" as="element()"/> 
    <xsl:value-of select="for $step in $target/ancestor-or-self::* return concat(name($step), '[', count($step/preceding-sibling::*[name() = name($step)]) + 1, ']')" separator="/"/> 
</xsl:function> 

然而,這種方法效率很低,因爲它必須遍歷重複的樹LY。請考慮:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="*"> 
    <xsl:param name="path"/> 
    <xsl:variable name="my-path"> 
     <xsl:value-of select="$path"/> 
     <xsl:text>/</xsl:text> 
     <xsl:value-of select="name()"/> 
     <xsl:text>[</xsl:text> 
     <xsl:value-of select="count(preceding-sibling::*[name() = name(current())]) + 1"/> 
     <xsl:text>]</xsl:text> 
    </xsl:variable> 
    <xsl:copy> 
     <xsl:attribute name="xpath"> 
      <xsl:value-of select="$my-path" />  
     </xsl:attribute> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates> 
      <xsl:with-param name="path" select="$my-path"/> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

它利用了XSLT的遞歸處理模型。

0

幾點。

(a)沒有「節點的XPath」這樣的事情。有些人在使用這樣一個術語時,意味着像a/b/c這樣的路徑,其他人將意味着a[1]/b[5]/c[6],而其他人則意味着通過在測試namespace-uri()的每個級別使用謂詞來完全命名空間限定的路徑。 (b)XPath 3.0提供了一個函數path(),它返回這種類型的XPath表達式;它使用EQName語法Q{uri}local確保元素名稱無上下文。

(三)我的辦法來獲取路徑要生成那種會

<xsl:function name="f:path" as="xs:string"> 
    <xsl:param name="e" as="element(*)"/> 
    <xsl:value-of select="ancestor-or-self::*/concat(
    '/', 
    name($e), 
    concat('[',f:index($e),']')[. ne '[1]'] 
)" separator=""/> 
</xsl:function> 

<xsl:function name="f:index" as="xs:integer"> 
    <xsl:param name="e" as="element(*)"/> 
    <xsl:sequence select="count(preceding-sibling::*[name()=name($e)])+1"/> 
</xsl:function> 

然後

<xsl:copy> 
    <xsl:attribute name="path" select="f:path(.)"/> 
    .... 
</xsl:copy> 
+0

我不認爲你已經測試過這些。 –

+0

我很少測試代碼示例。我認爲讀者應該理解代碼而不是逐字逐句地使用它是很重要的,而留下奇怪的錯誤有助於確保這一點。 –