Xml XSLT if属性存在/else
我对XSLT非常陌生,因此我想知道检查属性存在性的最佳实践是什么。我的XML如下所示:Xml XSLT if属性存在/else,xml,xslt,xpath,Xml,Xslt,Xpath,我对XSLT非常陌生,因此我想知道检查属性存在性的最佳实践是什么。我的XML如下所示: <root> <languages> <lang id="EN">English<lang> <lang id="FR">French<lang> <lang id="DE">German</lang> </languages> &
<root>
<languages>
<lang id="EN">English<lang>
<lang id="FR">French<lang>
<lang id="DE">German</lang>
</languages>
<items>
<item lang="EN">test 1</item>
<item>test 2</item>
<item lang="FR">item 3</item>
</items>
</root>
英语
法语
德国的
测试1
测试2
项目3
请注意,“item”元素的“lang”属性是可选的
现在我想使用-loop遍历这些项,同时检查它是否具有“lang”属性。如果是,我想使用ID(例如EN->“English”)获取整个字符串。如果属性没有设置,我希望它写“无语言集”或类似的东西
现在我使用下面的代码,但我在问自己是否不能以更有效的方式完成
<xsl:for-each select="//root/items/item">
<xsl:variable name="cur_lang" select="@lang" /> <!-- first I store the attr lang in a variable -->
<xsl:choose>
<xsl:when test="@lang"> <!-- then i test if the attr exists -->
<xsl:value-of select="//root/languages/lang[@id=$cur_lang]" /> <!-- if so, parse the element value -->
</xsl:when>
<xsl:otherwise>
No language set <!-- else -->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
没有语言集
有什么建议/提示吗?使用密钥可能更有效。使用模板外的顶级元素定义键
<xsl:key name="langByCode" match="lang" use="@id" />
有了这些模板,您就可以执行
,它会自动为每个项目选择合适的模板。规则是,它将使用最具体的模板,因此项[@lang]
一个用于具有lang
属性的项,而普通项
一个用于不具有该属性的项
第三种可能性是我学到的一个小技巧,将整个if/else检查放入一个XPath表达式中
<xsl:value-of select="
substring(
concat('No language set', key('langByCode', @lang)),
1 + (15 * boolean(@lang))
)" />
如果您能够使用XSLT 3.0,另一种选择是(另一个有用的链接:) XML输入(固定格式)
英语
法语
德国的
测试1
测试2
项目3
XSLT 3.0
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:xs="http://www.w3.org/2001/XMLSchema" extension-element-prefixes="xs map">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="lang-map" as="map(xs:string, xs:string)"
select="map:new(
for $lang in /*/languages/lang
return
map{$lang/@id := $lang/string()}
)"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="languages"/>
<xsl:template match="item[@lang and map:contains($lang-map,@lang)]">
<item><xsl:value-of select="$lang-map(current()/@lang)"/></item>
</xsl:template>
<xsl:template match="item">
<item>No language found.</item>
</xsl:template>
</xsl:stylesheet>
找不到语言。
输出
<root>
<items>
<item>English</item>
<item>No language found.</item>
<item>French</item>
</items>
</root>
英语
找不到语言。
法语
您可以添加一个示例,说明在您提供的输入中应该提供什么样的确切输出吗?Carlo,您忘记提供所需的输出了--我想您希望扩展语言字符串替换当前的lang
属性值。当转换应用于提供的XML文档时,请编辑问题并提供想要的结果。谢谢,我尝试使用,但当我这样做时,页面不会加载。我可能做错了什么?通过从现在开始移动解决了问题。如果有一个额外的可选属性,比如“color”,我该怎么办?@carlo我在另一个技巧上添加了一些注释(从Dimitre Novatchev这里开始),将if/else压缩到一个XPath表达式中,这意味着对于lang/no lang情况,不需要显式的if或单独的模板。
<xsl:value-of select="substring(
concat('No color specified', @color),
1 + (18 * boolean(@color))
)" />
<root>
<languages>
<lang id="EN">English</lang>
<lang id="FR">French</lang>
<lang id="DE">German</lang>
</languages>
<items>
<item lang="EN">test 1</item>
<item>test 2</item>
<item lang="FR">item 3</item>
</items>
</root>
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:xs="http://www.w3.org/2001/XMLSchema" extension-element-prefixes="xs map">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="lang-map" as="map(xs:string, xs:string)"
select="map:new(
for $lang in /*/languages/lang
return
map{$lang/@id := $lang/string()}
)"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="languages"/>
<xsl:template match="item[@lang and map:contains($lang-map,@lang)]">
<item><xsl:value-of select="$lang-map(current()/@lang)"/></item>
</xsl:template>
<xsl:template match="item">
<item>No language found.</item>
</xsl:template>
</xsl:stylesheet>
<root>
<items>
<item>English</item>
<item>No language found.</item>
<item>French</item>
</items>
</root>