如何在XSLT1中为同级Date含指定属性的Event元素应用模板?
我懂你的痛点——手里一堆针对不同Event场景的模板,不想每次都用xsl:if包裹或者在模板里加额外判断,就想直接精准选中符合条件的Event元素来应用模板对吧?
先理清楚问题根源:你要找的是SpecialEvent下的Event元素,但前提是这个SpecialEvent里的同级Date元素的@AllDayEvent属性值为1。你之前尝试的路径MeetingWorkBook/Meeting[1]/SpecialEvent/Event[Date[@AllDayEvent='1']]没生效,核心问题是路径的上下文判断错了——你写的Event[Date...]是在找Event的子节点Date,但根据你的XML结构,Date和Event是平级的,都属于SpecialEvent的子元素,所以这个条件永远匹配不到任何内容。
正确的解决方案
在XSLT 1.0里,你可以把条件放在父节点SpecialEvent上,先筛选出符合要求的SpecialEvent,再从中选中Event元素,这样就能直接精准匹配到你要的目标元素了。修改后的apply-templates代码如下:
<xsl:apply-templates select="MeetingWorkBook/Meeting[1]/SpecialEvent[Date[@AllDayEvent='1']]/Event" mode="FirstRow_Pray"> <xsl:with-param name="strClass">cellBold borderRight</xsl:with-param> </xsl:apply-templates>
为什么这个写法有效?
SpecialEvent[Date[@AllDayEvent='1']]会先筛选出所有包含Date子元素且@AllDayEvent='1'的SpecialEvent节点;- 然后再从这些符合条件的
SpecialEvent里选中Event元素,完全满足了“仅当Event存在且同级Date的@AllDayEvent为1时应用模板”的需求。
这个写法和你用xsl:if包裹的效果完全一致,但更贴合你想要的“直接选择目标元素”的思路,不用额外增加判断逻辑,也能和你现有的大量特定Event模板兼容。
用你的示例XML验证
拿你提供的示例XML来看,SpecialEvent下的Date元素确实有AllDayEvent="1",所以这个路径会成功选中<Event>Circuit Assembly - Love Jehovah With All Your Heart</Event>,并应用你的FirstRow_Pray模板,生成带rowspan="2"的td元素。
内容的提问来源于stack exchange,提问作者Andrew Truckle

