2013-08-23 43 views
1

這裏是我的source.xml:XSLT:如何使用一個變量作爲查找更新節點

<entries> 
    <entry path="/folder/abc.txt"> 
     <a>abc</a> 
     <b>baz</b> 
    </entry> 
    <entry path="/other/def.txt"> 
     <a>foo</a> 
     <b>bar</b> 
    </entry>  
</entries> 

我的XSLT是這樣的:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes"/> 
    <xsl:variable name="lookup"> 
     <pair> 
      <key>/folder/abc.txt</key> 
      <value>/other/folder/abc.txt</value> 
     </pair> 
     <pair> 
      <key>/other/def.txt</key> 
      <value>/other/folder/misc/def.txt</value> 
     </pair> 
    </xsl:variable> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

因此我可以重現我的源XML。我想要更新path使用變量lookup(其中path應匹配key返回value)。

最後的結果將是:

<entries> 
    <entry path="/other/folder/abc.txt"> 
     <a>abc</a> 
     <b>baz</b> 
    </entry> 
    <entry path="/other/folder/misc/def.txt"> 
     <a>foo</a> 
     <b>bar</b> 
    </entry>  
</entries> 

最新的要求是準確地保持縮進,因爲這是。

我該如何做到這一點?

在此先感謝。

回答

1

你可以把查找在一個單獨的文件,並使其與豆蔻清理容易:

lookup.xml:

<entries> 
    <entry path="/folder/abc.txt">/other/folder/abc.txt</entry> 
    <entry path="/other/def.txt">/other/folder/misc/def.txt</entry> 
</entries> 

您的XSLT:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" /> 

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


    <xsl:template match="entry/@path"> 
     <xsl:variable name="oldpath" select="." /> 
     <xsl:attribute name="path"><xsl:value-of 
      select="document('lookup.xml')/entries/entry[@path = $oldpath]" /></xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 

請注意,如果不匹配,解決方案將不會保留原始值。

2

以下XSL模板應該這樣做。它使用EXSLT擴展函數將變量轉換爲節點集。 (警告:如果在變量敵不過路徑,那麼路徑將被刪除)

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

    <xsl:variable name="lookup"> 
    <pair> 
     <key>/folder/abc.txt</key> 
     <value>/other/folder/abc.txt</value> 
    </pair> 
    <pair> 
     <key>/other/def.txt</key> 
     <value>/other/folder/misc/def.txt</value> 
    </pair> 
    </xsl:variable> 

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

    <xsl:template match="entry"> 
    <xsl:copy> 
     <xsl:attribute name="path"> 
     <xsl:call-template name="replace"> 
      <xsl:with-param name="input" select="@path"/> 
     </xsl:call-template> 
     </xsl:attribute> 
     <xsl:apply-templates select="*"/> 
    </xsl:copy> 
    </xsl:template> 

    <!-- This template looks through each pair in lookup, finds the one whose 
     key matches the input and returns the corresponding value. If none 
     match, nothing will be returned. -->  
    <xsl:template name="replace"> 
    <xsl:param name="input"/> 
    <xsl:for-each select="exslt:node-set($lookup)/pair"> 
     <xsl:if test="key = $input"> 
      <xsl:value-of select="value"/> 
     </xsl:if> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

你可以看到它的工作here

相關問題