我有一个带结构的xml,
<root>
<constant name="user">johndoe</constant>
<constant name="server">1</constant>
<connection>
<userName>${user}</userName>
<port>1234</port>
<server>matrix.${server}.abc.com</server>
</connection>
</root>
我正在使用XSLT将信息提取到CSV结构。如何用实际值替换常量名称?如果这可以在XSL中完成,那么我也有一些'嵌套'常量,例如,
<constant name="a">123</constant>
<constant name="b">10${a}</constant>
答案 0 :(得分:4)
由于您在评论中说您可以使用XSLT 2.0,因此它是analyze-string
的相对简单的用法:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:const="urn:const"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="const xs">
<!-- variable holding the input tree root for use inside analyze-string -->
<xsl:variable name="root" select="/"/>
<xsl:key name="constant" match="constant" use="@name" />
<!-- declare a function that you can call as const:replace(string) for any
string in which you want to expand out references to constants -->
<xsl:function name="const:replace" as="xs:string">
<xsl:param name="text" as="xs:string?" />
<xsl:variable name="result" as="xs:string*">
<xsl:analyze-string select="$text" regex="\$\{{(.*?)\}}">
<xsl:matching-substring>
<xsl:sequence select="key('constant', regex-group(1), $root)" />
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:sequence select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:variable>
<!-- analyze-string gives us a sequence of strings, join them into one
as the overall result of this function -->
<xsl:sequence select="string-join($result, '')" />
</xsl:function>
<!-- some templates to demonstrate the function in use -->
<!-- drop constant elements from output -->
<xsl:template match="constant" />
<!-- copy other elements and attributes unchanged -->
<xsl:template match="@*|*">
<xsl:copy><xsl:apply-templates select="@*, node()" /></xsl:copy>
</xsl:template>
<!-- expand ${constant} references in text nodes -->
<xsl:template match="text()">
<xsl:value-of select="const:replace(.)" />
</xsl:template>
</xsl:stylesheet>
魔术正则表达式为\$\{(.*?)\}
,但大括号字符必须加倍,因为regex
的{{1}}属性被视为attribute value template。
通过使函数递归
,在常量中处理常量是微不足道的analyze-string
一些警告:如果存在循环定义( <xsl:matching-substring>
<xsl:sequence select="const:replace(
key('constant', regex-group(1), $root))" />
</xsl:matching-substring>
,a=foo${b}
),这将进入无限循环,并且对未声明的常量的引用将消失(b=bar${a}
变为{{1虽然将函数调整为将这些标记为错误或保持不变是相当简单的。