为什么使用变量会更改xsl中的输出?

时间:2019-06-17 18:36:53

标签: xml xslt

我试图理解我的上一个问题的答案是如何工作的。这是一个古老的问题: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>

1 个答案:

答案 0 :(得分:2)

使用

main.jsbundle

仅为(外部 <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的一个只有一个。