选择属性不同的几个元素之一

时间:2011-08-01 23:59:56

标签: xslt attributes conditional

我是一名经验丰富的程序员,但他是XSLT的新手,我发现它非常令人费解。如果这是一个之前被问过的问题我很抱歉,但我对XSLT感到非常沮丧,我甚至不确定要搜索什么......

我有一个问题,如果某个XML元素只出现一次,我想要它的内容输出,但如果它多次出现,我只想要那些具有某个属性的内容。

例如,假设我有一个包含

的XML文件(称之为“文件1”)
<food>
    <snack>Chips</snack>
    <snack type="nuts">Peanuts</snack>
</food>

和另一个包含

的XML文件(“文件2”)
<food>
    <snack>Cheese puffs</snack>
</food>

我需要一个XSLT,在处理文件1时只输出“Peanuts”(但不是“Chips”),但仍然为文件2输出“Cheese puffs”(即我不能只选择那些具有“输入“属性,这太容易了”。

这可能很简单,但我被卡住了......

2 个答案:

答案 0 :(得分:1)

此转化

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

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

 <xsl:template match=
   "*[snack/@type]/snack[not(@type)]"/>
</xsl:stylesheet>

会在两种情况下产生想要的结果

<强>解释

  1. 身份规则/模板“按原样”复制每个节点

  2. 第二个模板覆盖任何snack元素的身份模板,但没有type属性,其中snack个元素具有{ {1}}属性。此模板具有空主体,可有效地“删除”匹配的元素(被复制到)输出。

答案 1 :(得分:0)

  

如果某个XML元素只出现一次,我希望它的内容输出,但如果它多次出现,我只想要那些具有某个属性的内容。

直接翻译是

if (count(snack) = 1) then snack else snack[@type='nuts']

这是有效的XPath 2.0语法 - 如果您需要在1.0中执行它,那么它会直接(尽管详细地)转换为等效的xsl:choose。

如果你想要比上面更简洁的东西,你也可以用XPath 2.0编写

(snack[@type='nuts'], snack)[1]

建立一个列表,首先包含type ='nuts'的小吃,然后是所有零食,然后从这个列表中选择第一个项目。