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

标签 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>

最佳答案

        <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/

相关文章:

xslt - 使用 XSLT 删除 XML 模式中多余的复杂类型

javascript - 如何使用 geoXML3 从外部 url 获取 KML?

java - JAXB如何生成可能带有嵌套元素的元素?

java - JAXB 和 JPA,关系

xml - 任何尚未处理的节点的 XSLT 模板?

xslt 匹配特定节点之前的所有节点

xslt - 将节点作为 XSL 模板参数传递

xml - 使用 Spark/Scala 从 XML 记录中提取元素

android - 如何在运行时修改xml中的颜色属性?

python - Python 2.5 是否包含一个包来本地转换 XML 文档?