我正在尝试了解我之前的问题的答案是如何工作的。这是老问题:XSL Transform with three source documents to create report
我有两个问题。 一,为什么变量的使用会导致节点“staff-with-membership”和“staff-with-membership-using-variable”(在 Center3 下)之间的输出发生变化。我的期望是使用变量不会有任何效果。
第二,“过滤”如何对变量“staff”起作用 - 我希望代码“key('membership-by-staff', @StaffID)”返回一个节点或不返回一个节点,但不知何故它似乎设法为“Center2”返回两个(查尔斯·格洛弗和唐纳德·希尔)。
源 XML:
<root>
<Staff>
<Items>
<Item StaffName="Charles Glover" StaffCenter="Center2" StaffID="CG1" />
<Item StaffName="Donald Hill" StaffCenter="Center2" StaffID="DH1" />
<Item StaffName="Evan Dolan" StaffCenter="Center3" StaffID="ED1" />
<Item StaffName="Frank Miller" StaffCenter="Center3" StaffID="FM1" />
</Items>
</Staff>
<Membership>
<Items>
<Item MembershipStaff_ID="CG1" />
<Item MembershipStaff_ID="DH1" />
<Item MembershipStaff_ID="ED1" />
</Items>
</Membership>
</root>
Xsl:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="staff-by-center" match="Staff/Items/Item" use="@StaffCenter"/>
<xsl:key name="membership-by-staff" match="Membership/Items/Item" use="@MembershipStaff_ID"/>
<xsl:template match="/root">
<root>
<!-- for each distinct center -->
<xsl:for-each select="Staff/Items/Item[count(.|key('staff-by-center', @StaffCenter)[1]) = 1]">
<xsl:variable name="center" select="@StaffCenter" />
<!-- staff at current center -->
<xsl:variable name="all-staff" select="key('staff-by-center', $center)" />
<!-- exclude staff with no memberships -->
<xsl:variable name="staff" select="$all-staff[key('membership-by-staff', @StaffID)]" />
<!-- staff using variable for StaffID instead of attribute -->
<xsl:variable name="myStaffId" select="@StaffID" />
<xsl:variable name="staff-using-variable" select="$all-staff[key('membership-by-staff', $myStaffId)]" />
<center>
<name>
<xsl:value-of select="$center" />
</name>
<all-staff-in-center>
<xsl:copy-of select="$all-staff" />
</all-staff-in-center>
<staff-with-membership>
<xsl:copy-of select="$staff" />
</staff-with-membership>
<membership>
<xsl:copy-of select="key('membership-by-staff', @StaffID)" />
</membership>
<staff-with-membership-using-variable>
<xsl:copy-of select="$staff-using-variable" />
</staff-with-membership-using-variable>
</center>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
输出XML:
<root>
<center>
<name>Center2</name>
<all-staff-in-center>
<Item StaffName="Charles Glover" StaffCenter="Center2" StaffID="CG1"/>
<Item StaffName="Donald Hill" StaffCenter="Center2" StaffID="DH1"/>
</all-staff-in-center>
<staff-with-membership>
<Item StaffName="Charles Glover" StaffCenter="Center2" StaffID="CG1"/>
<Item StaffName="Donald Hill" StaffCenter="Center2" StaffID="DH1"/>
</staff-with-membership>
<membership>
<Item MembershipStaff_ID="CG1"/>
</membership>
<staff-with-membership-using-variable>
<Item StaffName="Charles Glover" StaffCenter="Center2" StaffID="CG1"/>
<Item StaffName="Donald Hill" StaffCenter="Center2" StaffID="DH1"/>
</staff-with-membership-using-variable>
</center>
<center>
<name>Center3</name>
<all-staff-in-center>
<Item StaffName="Evan Dolan" StaffCenter="Center3" StaffID="ED1"/>
<Item StaffName="Frank Miller" StaffCenter="Center3" StaffID="FM1"/>
</all-staff-in-center>
<staff-with-membership>
<Item StaffName="Evan Dolan" StaffCenter="Center3" StaffID="ED1"/>
</staff-with-membership>
<membership>
<Item MembershipStaff_ID="ED1"/>
</membership>
<staff-with-membership-using-variable>
<Item StaffName="Evan Dolan" StaffCenter="Center3" StaffID="ED1"/>
<Item StaffName="Frank Miller" StaffCenter="Center3" StaffID="FM1"/>
</staff-with-membership-using-variable>
</center>
</root>
最佳答案
与
<xsl:variable name="myStaffId" select="@StaffID" />
<xsl:variable name="staff-using-variable" select="$all-staff[key('membership-by-staff', $myStaffId)]" />
您选择@StaffID
仅适用于上下文节点(外部 for-each
)的属性。
在表达式 <xsl:variable name="staff" select="$all-staff[key('membership-by-staff', @StaffID)]" />
中属性@StaffID
为 $all-staff
中的每个节点选择因为表达式位于方括号内的谓词内。您需要使用$all-staff[key('membership-by-staff', current()/@StaffID)]
获得与使用仅选择 StaffID
的变量相同的结果上下文节点。
至于$all-staff
被谓词 [key('membership-by-staff', @StaffID)]
过滤,对 $all-staff
中的每个节点计算谓词表达式。并测试 Membership/Items/Item
中是否有引用。 Center2
的两个人都有但仅适用于 Center3
之一。
关于xml - 为什么使用变量会改变 xsl 中的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56637048/