輸入xml檔案:
<a key="777">
<desc key="1" attr1="# {../@key}" attr2="{@key} #" attr3="555" title="{@attr2}">
<b attr3="444">
<slot key="2" attr3="333" attr4="{../../@attr3}" title="{../../@attr3} {../@attr3}-{@attr3}" >
<val key="3">
<fix key="4" title11="{../../@key} {../@key}" title="{@key} {@title11}" >
<c></c>
</fix>
</val>
<numb key="5" title12="z{@key}z in {@key}" title="{@title12} {@key}" titlew="{@title} {@title12}">
</numb>
</slot>
</b>
</desc>
</a>
大括號表示屬性的 XPath,您必須沿此 XPath 替換屬性的值,例如,代替 {@key} 和 {../@key},鍵屬性的值當前節點被替換。XSLT1.0 轉換后的檔案應如下所示:
<a key="777">
<desc key="1" attr1="# 777" attr2="1 #" attr3="555" title="1 #">
<b attr3="444">
<slot key="2" attr3="333" attr4="555" title="555 444-333">
<val key="3">
<fix key="4" title11="2 3" title="4 2 3">
<c />
</fix>
</val>
<numb key="5" title12="z5z in 5" title="z5z in 5 5" titlew="z5z in 5 5 z5z in 5" />
</slot>
</b>
</desc>
</a>
現在這是 XSLT1.0 轉換檔案:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{name()}">
<xsl:call-template name="expand">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:attribute>
</xsl:template>
<xsl:template name="expand">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '{@')">
<xsl:value-of select="substring-before($text, '{')"/>
<xsl:variable name="name" select="substring-before(substring-after($text, '{@'), '}')" />
<xsl:call-template name="expand">
<xsl:with-param name="text" select="../@*[name()=$name]"/>
</xsl:call-template>
<xsl:call-template name="expand">
<xsl:with-param name="text" select="substring-after($text, '}')"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($text, '{../@') ">
<xsl:value-of select="substring-before($text, '{')"/>
<xsl:variable name="name" select="substring-before(substring-after($text, '{../@'), '}')" />
<xsl:call-template name="expand">
<xsl:with-param name="text" select="../../@*[name()=$name]"/>
</xsl:call-template>
<xsl:call-template name="expand">
<xsl:with-param name="text" select="substring-after($text, '}')"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($text, '{../../@') ">
<xsl:value-of select="substring-before($text, '{')"/>
<xsl:variable name="name" select="substring-before(substring-after($text, '{../../@'), '}')" />
<xsl:call-template name="expand">
<xsl:with-param name="text" select="../../../@*[name()=$name]"/>
</xsl:call-template>
<xsl:call-template name="expand">
<xsl:with-param name="text" select="substring-after($text, '}')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
轉換后的xml檔案:
<a key="777">
<desc key="1" attr1="# 777" attr2="1 #" attr3="555" title="1 #">
<b attr3="444">
<slot key="2" attr3="333" attr4="555" title="333 333-333">
<val key="3">
<fix key="4" title11="3 3" title="4 3 3">
<c />
</fix>
</val>
<numb key="5" title12="z5z in 5" title="z5z in 5 5" titlew="z5z in 5 5 z5z in 5" />
</slot>
</b>
</desc>
</a>
錯誤是如果在輸入檔案節點的屬性值中指定了相同的屬性名稱,例如在花括號中的title屬性的Slot標簽中3次@attr3,那么相同的值被替換為花括號:
<slot key="2" ... title="333 333-333">
它應該是這樣的:
<slot key="2" ... title="555 444-333">
錯誤在哪里?
uj5u.com熱心網友回復:
在純 XSLT 1.0 中沒有真正好的解決方案。
如果輸入 XML 中的路徑運算式僅限于許多預定義模式(如您的示例中所示),您可以通過以下方式獲得預期結果:
XSLT 1.0
<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="node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{name()}">
<xsl:call-template name="expand">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:attribute>
</xsl:template>
<xsl:template name="expand">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '{') ">
<!-- text before reference -->
<xsl:value-of select="substring-before($text, '{')"/>
<!-- reference -->
<xsl:call-template name="evaluate">
<xsl:with-param name="path" select="substring-before(substring-after($text, '{'), '}')"/>
</xsl:call-template>
<!-- recursive call with text after reference -->
<xsl:call-template name="expand">
<xsl:with-param name="text" select="substring-after($text, '}')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="evaluate">
<xsl:param name="path"/>
<xsl:variable name="name" select="substring-after($path, '@')"/>
<xsl:call-template name="expand">
<xsl:with-param name="text">
<xsl:choose>
<xsl:when test="starts-with($path, '../../@')">
<xsl:value-of select="../../../@*[name()=$name]"/>
</xsl:when>
<xsl:when test="starts-with($path, '../@')">
<xsl:value-of select="../../@*[name()=$name]"/>
</xsl:when>
<xsl:when test="starts-with($path, '@')">
<xsl:value-of select="../@*[name()=$name]"/>
</xsl:when>
</xsl:choose>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
更好的解決方案是升級到支持 XSLT 3.0 或其他動態評估機制的處理器 - 正如您之前的一個問題中所建議的那樣。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/459321.html
上一篇:計算節點數R,xml2
