XSLT 仅在存在其他子节点属性时更改子节点

Posted

技术标签:

【中文标题】XSLT 仅在存在其他子节点属性时更改子节点【英文标题】:XSLT to change the child node only when other child node attribute is present 【发布时间】:2022-01-02 06:59:32 【问题描述】:

我需要更改 peci:Organization 是重复子节点的 XML 文件。 我需要更改,如果文件中存在 <peci:Organization_Type = 'Alternate_Cost_Center' 存在于员工的档案中时,我才需要这样做。

我一直在尝试下面的代码:

-----enter code here---
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wd="urn:com.workday/bsvc"
    xmlns:is="java:com.workday.esb.intsys.xpath.ParsedIntegrationSystemFunctions"
    xmlns:peci="urn:com.workday/peci" xmlns:this="urn:this-stylesheet"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xdiff="urn:com.workday/esb/xdiff"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:op="http://www.w3.org/2005/xpath-functions" version="2.0"
    exclude-result-prefixes="xsl wd this xsd op xdiff peci xsi is">
    <xsl:output indent="yes" method="xml" />
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
        <xsl:template match="peci:Organization_Type">
            <xsl:copy>
                <xsl:choose>
                    <xsl:when test=". = 'Alternate_Cost_Center'">
                    <xsl:value-of select="'Cost_Center'" />
                    </xsl:when>
                    <xsl:when test=". = 'Cost_Center'">
                        <xsl:value-of select="'Dummy_Cost_Center'" />
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="." />
                    </xsl:otherwise>    
                </xsl:choose>
            </xsl:copy>
        </xsl:template>
</xsl:stylesheet>

**Example XML:**
    <?xml version="1.0" encoding="UTF-8"?>
    
    -<peci:Worker_Effective_Stack_Aggregate xmlns:peci="urn:com.workday/peci">
    -<peci:Workers_Effective_Stack>
    -<peci:Summary>     <peci:Integration_Event>da1c439dcf86011a442a9562d9960000</peci:Integration_Event>    
    <peci:Integration_Sent_On>20211121T07:52:23</peci:Integration_Sent_On>    <peci:Payroll_Company_ID>Payroll_Company_Jabil_Switzerland</peci:Payroll_Company_ID>
       <peci:Payroll_Company_Name>Jabil - Switzerland</peci:Payroll_Company_Name>
        <peci:Payroll_Company_Code>5200</peci:Payroll_Company_Code>
        <peci:Pay_Group_ID>C1</peci:Pay_Group_ID>
        <peci:Pay_Group_Name>CHE - Monthly - 5200</peci:Pay_Group_Name>
        <peci:Pay_Group_Country>CH</peci:Pay_Group_Country>
        <peci:Pay_Group_Code>C1</peci:Pay_Group_Code>
        <peci:Pay_Period_Start>20211101</peci:Pay_Period_Start>
        <peci:Pay_Period_End>20211130</peci:Pay_Period_End>
        <peci:Updated_From>20210601T10:25:54</peci:Updated_From>
        <peci:Updated_To>20211121T07:52:23</peci:Updated_To>
        <peci:Effective_From>20211101</peci:Effective_From>
        <peci:Effective_To>20211130</peci:Effective_To>
        <peci:Change_Detection>Include only changes entered since the last successful run.</peci:Change_Detection>       <peci:First_Primary_Run_of_Pay_Period>0</peci:First_Primary_Run_of_Pay_Period>
     <peci:Ad_Hoc_Run>1</peci:Ad_Hoc_Run>
        <peci:Full_Snapshot>0</peci:Full_Snapshot>
        <peci:Worker_Count>1</peci:Worker_Count>    
    <peci:Version>1</peci:Version>    
    </peci:Summary>        
    -<peci:Worker>    
    -<peci:Worker_Summary>    
    <peci:WID>4d73f467a8440137745f162288014b40</peci:WID>    
    <peci:Employee_ID>3062905</peci:Employee_ID>
    <peci:Name>Anna Conti</peci:Name>    
    </peci:Worker_Summary>        
    -<peci:Effective_Change peci:Sequence="0">    
    <peci:Derived_Event_Code>DTA</peci:Derived_Event_Code>    
    <peci:Effective_Moment>19000101T00:00:00</peci:Effective_Moment>
    <peci:Entry_Moment>20211109T10:17:13</peci:Entry_Moment>        
    -<peci:Position peci:isUpdated="1">    
    <peci:Position_ID>P3341022</peci:Position_ID>
     <peci:Position_Time_Type>Full_time</peci:Position_Time_Type>    
    <peci:Job_Profile>51016106</peci:Job_Profile>        
    -<peci:Supervisor>
       <peci:ID>2115831</peci:ID>    
    <peci:Name>Damian Gruber</peci:Name>    
    </peci:Supervisor>
    -<peci:Organization>
      <peci:Organization_Type>Cost_Center</peci:Organization_Type>
        <peci:Organization_Code>30900498</peci:Organization_Code>    
    <peci:Organization_Name>General Above Site</peci:Organization_Name>    
    </peci:Organization>    
    -<peci:Organization>    
    <peci:Organization_Type>Alternate_Cost_Center</peci:Organization_Type>    
    <peci:Organization_Code>31020420</peci:Organization_Code>    
    <peci:Organization_Name>JJMD - Finance Europe</peci:Organization_Name>    
    </peci:Organization>    
        -<peci:Organization peci:isUpdated="1">
        <peci:Organization_Type>Pay_Group</peci:Organization_Type>
        <peci:Organization_Code peci:isAdded="1">C1</peci:Organization_Code>
        <peci:Organization_Name>CHE - Monthly -5200</peci:Organization_Name>
        </peci:Organization>
       -<peci:Organization>
        <peci:Organization_Type>Supervisory</peci:Organization_Type>
        <peci:Organization_Code>2202783</peci:Organization_Code>    
<peci:Organization_Name>Financial Planning Analysis</peci:Organization_Name>
        </peci:Organization>
            -<peci:Organization>    
    <peci:Organization_Type>Company</peci:Organization_Type>    
    <peci:Organization_Code>5200</peci:Organization_Code>    <peci:Organization_Name>Jabil Switzerland Manufacturing GmbH</peci:Organization_Name>
        </peci:Organization>    
    <ptdf:HR_Admin xmlns:ptdf="urn:com.workday/peci/tdf">N</ptdf:HR_Admin>    
    <ptdf:Position_Name xmlns:ptdf="urn:com.workday/peci/tdf">Sr. Financial Analyst</ptdf:Position_Name>    
    <ptdf:Job_Profile_Name xmlns:ptdf="urn:com.workday/peci/tdf">Sr. Financial Analyst</ptdf:Job_Profile_Name>    
    <ptdf:Employee_Group xmlns:ptdf="urn:com.workday/peci/tdf">1</ptdf:Employee_Group>
        <ptdf:Employee_Subgroup xmlns:ptdf="urn:com.workday/peci/tdf">C1</ptdf:Employee_Subgroup>
        <ptdf:Personnel_Area xmlns:ptdf="urn:com.workday/peci/tdf">C210</ptdf:Personnel_Area>
    <ptdf:Personnel_SubArea xmlns:ptdf="urn:com.workday/peci/tdf">5204</ptdf:Personnel_SubArea>
    <ptdf:Business_Area xmlns:ptdf="urn:com.workday/peci/tdf">5204</ptdf:Business_Area>
        <ptdf:Work_Schedule xmlns:ptdf="urn:com.workday/peci/tdf">S540000</ptdf:Work_Schedule>
        </peci:Position>
        -<peci:Additional_Information>
        <peci:WorkerID>4d73f467a8440137745f162288014b40</peci:WorkerID>
        </peci:Additional_Information>
        </peci:Effective_Change>
       -<peci:Effective_Change peci:Sequence="1">
        <peci:Derived_Event_Code>HIR-R</peci:Derived_Event_Code>    
    <peci:Effective_Moment>20210801T00:00:00</peci:Effective_Moment>    
    <peci:Entry_Moment>20210818T02:26:42</peci:Entry_Moment>
            -<peci:Worker_Status>    
    <peci:Status>Active</peci:Status>    
    <peci:Active>0</peci:Active>    
    <peci:Active_Status_Date>20210801</peci:Active_Status_Date>    
    <peci:Terminated>0</peci:Terminated>    
    <peci:Hire_Date>20210801</peci:Hire_Date>    
    <peci:Original_Hire_Date>20210816</peci:Original_Hire_Date> <peci:Hire_Reason>General_Event_Subcategory_New_Hire_Replacement</peci:Hire_Reason>
    <peci:Continuous_Service_Date>20210801</peci:Continuous_Service_Date>
    <peci:First_Day_of_Work>20210801</peci:First_Day_of_Work>
    <peci:Seniority_Date>20210816</peci:Seniority_Date>
    </peci:Worker_Status>
    -<peci:Additional_Information>
    <peci:WorkerID>4d73f467a8440137745f162288014b40</peci:WorkerID>
    </peci:Additional_Information>
    </peci:Effective_Change>
    <peci:Effective_Change peci:Sequence="2">    
    <peci:Derived_Event_Code>HIR</peci:Derived_Event_Code>
        <peci:Effective_Moment>20210816T00:00:00</peci:Effective_Moment>    
    <peci:Entry_Moment>20210818T02:26:42</peci:Entry_Moment>        
    -<peci:Worker_Status peci:isUpdated="1">    
    <peci:Status>Active</peci:Status>    
    <peci:Active peci:priorValue="0">1</peci:Active>    
    <peci:Active_Status_Date peci:priorValue="20210801">20210816</peci:Active_Status_Date>    
    <peci:Terminated>0</peci:Terminated>    
    <peci:Hire_Date peci:priorValue="20210801">20210816</peci:Hire_Date>    
    <peci:Original_Hire_Date peci:priorValue="20210801">20210816</peci:Original_Hire_Date> <peci:Hire_Reason>General_Event_Subcategory_New_Hire_Replacement</peci:Hire_Reason>
    <peci:Continuous_Service_Date peci:priorValue="20210801">20210816</peci:Continuous_Service_Date>
    <peci:First_Day_of_Work peci:priorValue="20210801">20210816</peci:First_Day_of_Work>
    <peci:Seniority_Date peci:priorValue="20210801">20210816</peci:Seniority_Date>
    </peci:Worker_Status>
    </peci:Effective_Change>
    </peci:Worker>
    </peci:Workers_Effective_Stack>
    </peci:Worker_Effective_Stack_Aggregate>

预期输出:

-<peci:Organization>
<peci:Organization_Type>Dummy_Cost_Center</peci:Organization_Type>
<peci:Organization_Code>30900498</peci:Organization_Code>
<peci:Organization_Name>General Above Site</peci:Organization_Name>
</peci:Organization>
-<peci:Organization>
<peci:Organization_Type>Cost_Center</peci:Organization_Type>
<peci:Organization_Code>31020420</peci:Organization_Code>
<peci:Organization_Name>JJMD - Finance Europe</peci:Organization_Name>
</peci:Organization>

&lt;peci:Organization_Type&gt;Alternate_Cost_Center&lt;/peci:Organization_Type&gt; 存在时,我的 XSLT 代码工作正常。 但是当它不存在时,&lt;peci:Organization_Type&gt;Cost_Center&lt;/peci:Organization_Type&gt; 将更改为 Dummy_Cost_Center。 我不想要这个,我只想在peci:Organization_Type&gt;Alternate_Cost_Center&lt;/peci:Organization_Type&gt; 出现在员工面前时进行更改。

【问题讨论】:

【参考方案1】:

您可以通过简单地使用两个“替换”模板来做到这一点:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wd="urn:com.workday/bsvc"
    xmlns:is="java:com.workday.esb.intsys.xpath.ParsedIntegrationSystemFunctions"
    xmlns:peci="urn:com.workday/peci" xmlns:this="urn:this-stylesheet"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xdiff="urn:com.workday/esb/xdiff"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:op="http://www.w3.org/2005/xpath-functions" version="2.0"
    exclude-result-prefixes="xsl wd this xsd op xdiff peci xsi is">
    <xsl:output indent="yes" method="xml" />
    
    <!-- Identity template -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="peci:Organization[peci:Organization_Type='Alternate_Cost_Center']">
        <xsl:copy>
            <peci:Organization_Type>Cost_Center</peci:Organization_Type>
            <xsl:copy-of select="peci:*[name()!='peci:Organization_Type']" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="peci:Organization[peci:Organization_Type='Cost_Center' and //peci:Organization_Type='Alternate_Cost_Center']">
        <xsl:copy>
            <peci:Organization_Type>Dummy_Cost_Center</peci:Organization_Type>
            <xsl:copy-of select="peci:*[name()!='peci:Organization_Type']" />
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

输出应该符合预期。 当且仅当peci:Organization_Type 匹配所需值时,这两个模板将所需元素与谓词匹配。否则只会执行身份模板

编辑: 现在第二个模板只有在整个文件中存在Organization_Type='Alternate_Cost_Center' 节点时才会执行。如果您只需要检查此节点在同一级别,请改用以下模板匹配规则:

<xsl:template match="peci:Organization[peci:Organization_Type='Cost_Center' and ../peci:Organization/peci:Organization_Type='Alternate_Cost_Center']">
    <xsl:copy>
        <peci:Organization_Type>Dummy_Cost_Center</peci:Organization_Type>
        <xsl:copy-of select="peci:*[name()!='peci:Organization_Type']" />
    </xsl:copy>
</xsl:template>

【讨论】:

嗨,这会将 peci:Organization_Type 成本中心更改为虚拟成本中心,如果备用成本中心不存在,则事件......所以我的要求是,当只有成本中心存在时什么都不会发生,并且此 XSLT 仅在存在备用成本中心时运行。我希望我能够传达这个问题。 我更新了答案以更好地反映您的要求。现在Cost Center 仅在文件中或同一级别存在Alternative Cost Center 时才会更改。【参考方案2】:

我已经设法编写了以下xslt 代码,这符合我的要求:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:etv="urn:com.workday/etv" xmlns:peci="urn:com.workday/peci" xmlns:this="urn:this-stylesheet" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xtt="urn:com.workday/xtt" exclude-result-prefixes="xs this" version="2.0">
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="peci:Worker/peci:Effective_Change/peci:Position/peci:Organization[peci:Organization_Type = 'Cost_Center']/peci:Organization_Type">
    <xsl:choose>
      <xsl:when test="exists(current()/../../peci:Organization[peci:Organization_Type = 'Alternate_Cost_Center'])">
        <xsl:copy>
          <xsl:value-of select="'Dummy_Cost_Center'" />
        </xsl:copy>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy>
          <xsl:value-of select="'Cost_Center'" />
        </xsl:copy>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <xsl:template match="peci:Worker/peci:Effective_Change/peci:Position/peci:Organization[peci:Organization_Type = 'Alternate_Cost_Center']/peci:Organization_Type">
    <xsl:copy>
      <xsl:value-of select="'Cost_Center'" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

【讨论】:

以上是关于XSLT 仅在存在其他子节点属性时更改子节点的主要内容,如果未能解决你的问题,请参考以下文章

高手帮忙:sql 里怎样递归判断父节点和子节

删除节点(removeChild())

XSLT:分析字符串并保留子节点

TreeView 点击触发父节点子节点的连锁反应选中与取消

计算特定XML节点c#的子节点数[重复]

数据结构-树:根节点子节点叶子节点是什么?