我们的软件具有用户可编辑的XML配置文件,然后在我们的Java应用程序中进行解组。我们希望允许我们或我们的用户能够添加要在配置文件中的字符串中使用的新变量。
我有这种结构的XML:
<root>
<variables>
<key1>foo</key1>
<key2>bar</key1>
...
<keyn>nthbar</keyn>
</variables>
<some-tag>PlainText.${key1}.${keyn}.${key2}.MorePlainText</some-tag>
<other-tag>${key3}</other-tag>
</root>
我知道我可以使用XSLT 2.0做这样的事情来替换已知密钥的值:
<xsl:variable name="key1" select="root/variables/key1/text()" />
<xsl:variable name="key2" select="root/variables/key1/text()" />
...
<xsl:variable name="keyn" select="root/variables/key1/text()" />
<xsl:template match="text()">
<xsl:value-of select="replace( replace( replace( ., '\$\{val1\}', $key1), '\$\{val2\}', $key2), '\$\{valn\}', $keyn)" />
</xsl:template>
麻烦的是,这不是很灵活。每次添加新密钥时,新的replace()都需要包装现有的replace()调用,并且需要在相应的xsl文件中声明一个新变量。
使用XSLT通过在XML文件的其他位置使用字符串中的$ {keyn}之类的东西来引用像value这样的标记是否有一种灵巧的方式?
答案 0 :(得分:1)
您可以使用密钥匹配variables/*
个元素,然后使用analyze-string
在文本节点中查找{$var}
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:key name="variables" match="variables/*" use="local-name()"/>
<xsl:variable name="main-root" select="/"/>
<xsl:template match="@* | * | comment() | processing-instruction()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/variables"/>
<xsl:param name="variable-pattern" as="xs:string">\$\{(\w+)\}</xsl:param>
<xsl:template match="text()">
<xsl:analyze-string select="." regex="{$variable-pattern}">
<xsl:matching-substring>
<xsl:value-of select="key('variables', regex-group(1), $main-root)"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>
我想如果找到匹配但key('variables', regex-group(1), $main-root)
找不到任何定义,最好引发错误:
<xsl:template match="text()">
<xsl:analyze-string select="." regex="{$variable-pattern}">
<xsl:matching-substring>
<xsl:variable name="var-match" select="key('variables', regex-group(1), $main-root)"/>
<xsl:choose>
<xsl:when test="$var-match">
<xsl:value-of select="$var-match"/>
</xsl:when>
<xsl:otherwise>
<xsl:message select="concat('No match found for $', regex-group(1))"/>
</xsl:otherwise>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>