XSLT XPath:如果更新了一个子节点,则从不同的子节点获取数据(对于同一工作人员)-如何处理?
XSLT XPath: If one child node is updated, take data from different child node (for the same worker) - how to handle?
这是我的XML(见下面的问题):
<?xml version="1.0" encoding="UTF-8"?>
<Worker_Effective_Stack_Aggregate>
<Pay_Group Name="Exempt">
<Worker>
<Summary>
<Employee_ID>12345</Employee_ID>
</Summary>
<Effective_Change>
<Derived_Event_Code>PGO</Derived_Event_Code>
<Position isUpdated="1">
<Business_Title>Test Worker</Business_Title>
<Position_End_Date isAdded="1">6/30/2021</Position_End_Date>
</Position>
</Effective_Change>
</Worker>
</Pay_Group>
<Pay_Group Name="Non-Exempt">
<Worker>
<Summary>
<Employee_ID>11111</Employee_ID>
</Summary>
<Effective_Change>
<Derived_Event_Code>PGI</Derived_Event_Code>
<Position isAdded="1">
<Business_Title>Wrong Test Worker</Business_Title>
</Position>
</Effective_Change>
</Worker>
<Worker>
<Summary>
<Employee_ID>12345</Employee_ID>
</Summary>
<Effective_Change>
<Derived_Event_Code>PGI</Derived_Event_Code>
<Position isAdded="1">
<Business_Title>Senior Test Worker</Business_Title>
</Position>
</Effective_Change>
</Worker>
</Pay_Group>
</Worker_Effective_Stack_Aggregate>
问题:你知道如何编写代码来遵循这个场景:'如果事件代码是'PGO'并且工人的位置更新为结束日期,在整个文件中查找与发生 'PGO' 事件的工人 ID 相同的工人的 'PGI' 事件 并提供 的 值,在本例中为 'Senior Test Worker'.
这是我的 XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xtt="urn:com.workday/xtt" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="SEPARATOR" select="','" as="xs:string"/>
<xsl:variable name="NEWLINE" select="'
'" as="xs:string"/>
<xsl:template match="/">
<File>
<Header xtt:endTag="{$NEWLINE}" xtt:separator="{$SEPARATOR}">
<Business_Title>Business Title</Business_Title>
</Header>
<xsl:apply-templates select="Worker_Effective_Stack_Aggregate/Pay_Group/Worker"/>
</File>
</xsl:template>
<xsl:template match="Worker">
<Employee xtt:endTag="{$NEWLINE}" xtt:separator="{$SEPARATOR}" xtt:quotes="never">
<Business_Title>
<xsl:choose>
<xsl:when test="Effective_Change/Derived_Event_Code = 'PGO'">
<xsl:value-of select="../../../Worker_Effective_Stack_Aggregate/Pay_Group/Worker [Effective_Change/Derived_Event_Code = 'PGI' and Summary/Employee_ID = '12345']/Effective_Change/Position/Business_Title"/>
</xsl:when>
</xsl:choose>
</Business_Title>
</Employee>
</xsl:template>
</xsl:stylesheet>
如果您需要上述所有内容的背景知识:在我们的 HCM 系统中 'Workday',每当有人更改薪酬组和职位时,Workday 都会为他们创建两个事件,一个称为 'PGO'(支付组出站),第二个称为 'PGI'(支付组入站)。如果位置发生变化,新的只会反映在 'PGI' 事件中,我需要以某种方式将其带入 'PGO' 事件详细信息中。
预期输出:
<?xml version="1.0"?>
<File xmlns:xtt="urn:com.workday/xtt">
<Header xtt:endTag=" " xtt:separator=",">
<Business_Title>Business Title</Business_Title>
</Header>
<Employee xtt:endTag=" " xtt:separator="," xtt:quotes="never">
<Business_Title>Senior Test Worker</Business_Title>
</Employee>
<Employee xtt:endTag=" " xtt:separator="," xtt:quotes="never">
<Business_Title/>
</Employee>
<Employee xtt:endTag=" " xtt:separator="," xtt:quotes="never">
<Business_Title/>
</Employee>
</File>
使用基于键和模板的匹配,您可以使用
从相关元素中提取标题
<xsl:key name="bus-title-by-id"
match="Worker/Effective_Change[Derived_Event_Code = 'PGI']/Position/Business_Title"
use="ancestor::Worker/Summary/Employee_ID"/>
<xsl:template match="Worker/Effective_Change[Derived_Event_Code = 'PGO']/Position[@isUpdated = 1][Position_End_Date]/Business_Title[key('bus-title-by-id', ancestor::Worker/Summary/Employee_ID)]">
<xsl:sequence select="key('bus-title-by-id', ancestor::Worker/Summary/Employee_ID)"/>
</xsl:template>
如果文档的其余部分需要原封不动地复制,请使用身份转换模板进行处理
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
至于你自己的代码,现在添加,使用current()
比较两个元素(即一个与你查找的另一个匹配):
<xsl:template match="Worker">
<Employee xtt:endTag="{$NEWLINE}" xtt:separator="{$SEPARATOR}" xtt:quotes="never">
<Business_Title>
<xsl:choose>
<xsl:when test="Effective_Change/Derived_Event_Code = 'PGO'">
<xsl:value-of select="../../../Worker_Effective_Stack_Aggregate/Pay_Group/Worker [Effective_Change/Derived_Event_Code = 'PGI' and Summary/Employee_ID = current()/Summary/Employee_ID]/Effective_Change/Position/Business_Title"/>
</xsl:when>
</xsl:choose>
</Business_Title>
</Employee>
</xsl:template>
最后,密钥的使用使此类查找更快更有效:
<xsl:template match="Worker">
<Employee xtt:endTag="{$NEWLINE}" xtt:separator="{$SEPARATOR}" xtt:quotes="never">
<Business_Title>
<xsl:choose>
<xsl:when test="Effective_Change/Derived_Event_Code = 'PGO'">
<xsl:value-of select="key('bus-title-by-id', Summary/Employee_ID)"/>
</xsl:when>
</xsl:choose>
</Business_Title>
</Employee>
</xsl:template>
<xsl:key name="bus-title-by-id"
match="Worker/Effective_Change[Derived_Event_Code = 'PGI']/Position/Business_Title"
use="ancestor::Worker/Summary/Employee_ID"/>
在最后两个示例中,xsl:choose/when
似乎不必要地复杂,一个简单的 xsl:if
就足够了。
这是我的XML(见下面的问题):
<?xml version="1.0" encoding="UTF-8"?>
<Worker_Effective_Stack_Aggregate>
<Pay_Group Name="Exempt">
<Worker>
<Summary>
<Employee_ID>12345</Employee_ID>
</Summary>
<Effective_Change>
<Derived_Event_Code>PGO</Derived_Event_Code>
<Position isUpdated="1">
<Business_Title>Test Worker</Business_Title>
<Position_End_Date isAdded="1">6/30/2021</Position_End_Date>
</Position>
</Effective_Change>
</Worker>
</Pay_Group>
<Pay_Group Name="Non-Exempt">
<Worker>
<Summary>
<Employee_ID>11111</Employee_ID>
</Summary>
<Effective_Change>
<Derived_Event_Code>PGI</Derived_Event_Code>
<Position isAdded="1">
<Business_Title>Wrong Test Worker</Business_Title>
</Position>
</Effective_Change>
</Worker>
<Worker>
<Summary>
<Employee_ID>12345</Employee_ID>
</Summary>
<Effective_Change>
<Derived_Event_Code>PGI</Derived_Event_Code>
<Position isAdded="1">
<Business_Title>Senior Test Worker</Business_Title>
</Position>
</Effective_Change>
</Worker>
</Pay_Group>
</Worker_Effective_Stack_Aggregate>
问题:你知道如何编写代码来遵循这个场景:'如果事件代码是'PGO'并且工人的位置更新为结束日期,在整个文件中查找与发生 'PGO' 事件的工人 ID 相同的工人的 'PGI' 事件 并提供
这是我的 XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xtt="urn:com.workday/xtt" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="SEPARATOR" select="','" as="xs:string"/>
<xsl:variable name="NEWLINE" select="'
'" as="xs:string"/>
<xsl:template match="/">
<File>
<Header xtt:endTag="{$NEWLINE}" xtt:separator="{$SEPARATOR}">
<Business_Title>Business Title</Business_Title>
</Header>
<xsl:apply-templates select="Worker_Effective_Stack_Aggregate/Pay_Group/Worker"/>
</File>
</xsl:template>
<xsl:template match="Worker">
<Employee xtt:endTag="{$NEWLINE}" xtt:separator="{$SEPARATOR}" xtt:quotes="never">
<Business_Title>
<xsl:choose>
<xsl:when test="Effective_Change/Derived_Event_Code = 'PGO'">
<xsl:value-of select="../../../Worker_Effective_Stack_Aggregate/Pay_Group/Worker [Effective_Change/Derived_Event_Code = 'PGI' and Summary/Employee_ID = '12345']/Effective_Change/Position/Business_Title"/>
</xsl:when>
</xsl:choose>
</Business_Title>
</Employee>
</xsl:template>
</xsl:stylesheet>
如果您需要上述所有内容的背景知识:在我们的 HCM 系统中 'Workday',每当有人更改薪酬组和职位时,Workday 都会为他们创建两个事件,一个称为 'PGO'(支付组出站),第二个称为 'PGI'(支付组入站)。如果位置发生变化,新的只会反映在 'PGI' 事件中,我需要以某种方式将其带入 'PGO' 事件详细信息中。
预期输出:
<?xml version="1.0"?>
<File xmlns:xtt="urn:com.workday/xtt">
<Header xtt:endTag=" " xtt:separator=",">
<Business_Title>Business Title</Business_Title>
</Header>
<Employee xtt:endTag=" " xtt:separator="," xtt:quotes="never">
<Business_Title>Senior Test Worker</Business_Title>
</Employee>
<Employee xtt:endTag=" " xtt:separator="," xtt:quotes="never">
<Business_Title/>
</Employee>
<Employee xtt:endTag=" " xtt:separator="," xtt:quotes="never">
<Business_Title/>
</Employee>
</File>
使用基于键和模板的匹配,您可以使用
从相关元素中提取标题 <xsl:key name="bus-title-by-id"
match="Worker/Effective_Change[Derived_Event_Code = 'PGI']/Position/Business_Title"
use="ancestor::Worker/Summary/Employee_ID"/>
<xsl:template match="Worker/Effective_Change[Derived_Event_Code = 'PGO']/Position[@isUpdated = 1][Position_End_Date]/Business_Title[key('bus-title-by-id', ancestor::Worker/Summary/Employee_ID)]">
<xsl:sequence select="key('bus-title-by-id', ancestor::Worker/Summary/Employee_ID)"/>
</xsl:template>
如果文档的其余部分需要原封不动地复制,请使用身份转换模板进行处理
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
至于你自己的代码,现在添加,使用current()
比较两个元素(即一个与你查找的另一个匹配):
<xsl:template match="Worker">
<Employee xtt:endTag="{$NEWLINE}" xtt:separator="{$SEPARATOR}" xtt:quotes="never">
<Business_Title>
<xsl:choose>
<xsl:when test="Effective_Change/Derived_Event_Code = 'PGO'">
<xsl:value-of select="../../../Worker_Effective_Stack_Aggregate/Pay_Group/Worker [Effective_Change/Derived_Event_Code = 'PGI' and Summary/Employee_ID = current()/Summary/Employee_ID]/Effective_Change/Position/Business_Title"/>
</xsl:when>
</xsl:choose>
</Business_Title>
</Employee>
</xsl:template>
最后,密钥的使用使此类查找更快更有效:
<xsl:template match="Worker">
<Employee xtt:endTag="{$NEWLINE}" xtt:separator="{$SEPARATOR}" xtt:quotes="never">
<Business_Title>
<xsl:choose>
<xsl:when test="Effective_Change/Derived_Event_Code = 'PGO'">
<xsl:value-of select="key('bus-title-by-id', Summary/Employee_ID)"/>
</xsl:when>
</xsl:choose>
</Business_Title>
</Employee>
</xsl:template>
<xsl:key name="bus-title-by-id"
match="Worker/Effective_Change[Derived_Event_Code = 'PGI']/Position/Business_Title"
use="ancestor::Worker/Summary/Employee_ID"/>
在最后两个示例中,xsl:choose/when
似乎不必要地复杂,一个简单的 xsl:if
就足够了。