问题
I have a requirement to copy the child node from one parent to another based on a employee match but needs to place in a separate node. I have almost got the solution using key, but I am not able to paste the child node in a new separate node.
I developed the below code using key function:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wd="urn:com.workday/bsvc"
exclude-result-prefixes="xs xsd"
version="2.0">
<xsl:output indent="yes"/>
<xsl:key name="kEmpID" match="wd:Worker_Data"
use="concat(ancestor::wd:LeaveStatus/wd:LeaveDetail,wd:EmpID)"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="wd:ChangeEvent/wd:EventDetails">
<xsl:variable name="vLeaveStatus"
select="key('kEmpID',../wd:EmpID)"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<wd:Event>
<xsl:apply-templates
select="$vLeaveStatus/wd:LeaveStatus/wd:LeaveDetail/."/>
</wd:Event>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Below is the actual input:
<?xml version='1.0' encoding='utf-8'?>
<wd:Census_Report xmlns:wd="urn:com.workday/bsvc">
<wd:Workers>
<wd:Worker_Data>
<wd:EmpID>50211</wd:EmpID>
<wd:LeaveStatus>
<wd:LeaveDetail>
<wd:LOA_Start_Date>2017-12-22</wd:LOA_Start_Date>
<wd:LOA_End_Date>2018-01-22</wd:LOA_End_Date>
</wd:LeaveDetail>
<wd:LeaveDetail>
<wd:LOA_Start_Date>2018-02-20</wd:LOA_Start_Date>
<wd:LOA_End_Date>2018-03-02</wd:LOA_End_Date>
</wd:LeaveDetail>
</wd:LeaveStatus>
</wd:Worker_Data>
</wd:Workers>
<wd:ChangeEventSummary>
<wd:ChangeEvent>
<wd:EmpID>50211</wd:EmpID>
<wd:TermDate>2018-04-27</wd:TermDate>
<wd:EventDetails/>
</wd:ChangeEvent>
</wd:ChangeEventSummary>
</wd:Census_Report>
The below output is the expected output:
<?xml version="1.0" encoding="UTF-8"?>
<wd:Census_Report xmlns:wd="urn:com.workday/bsvc">
<wd:Workers>
<wd:Worker_Data>
<wd:EmpID>50211</wd:EmpID>
<wd:LeaveStatus>
<wd:LeaveDetail>
<wd:LOA_Start_Date>2017-12-22</wd:LOA_Start_Date>
<wd:LOA_End_Date>2018-01-22</wd:LOA_End_Date>
</wd:LeaveDetail>
<wd:LeaveDetail>
<wd:LOA_Start_Date>2018-02-20</wd:LOA_Start_Date>
<wd:LOA_End_Date>2018-03-02</wd:LOA_End_Date>
</wd:LeaveDetail>
</wd:LeaveStatus>
</wd:Worker_Data>
</wd:Workers>
<wd:ChangeEventSummary>
<wd:ChangeEvent>
<wd:EmpID>50211</wd:EmpID>
<wd:TermDate>2018-04-27</wd:TermDate>
<wd:EventDetails>
<wd:Event>
<wd:LeaveDetail>
<wd:LOA_Start_Date>2017-12-22</wd:LOA_Start_Date>
<wd:LOA_End_Date>2018-01-22</wd:LOA_End_Date>
</wd:LeaveDetail>
</wd:Event>
<wd:Event>
<wd:LeaveDetail>
<wd:LOA_Start_Date>2018-02-20</wd:LOA_Start_Date>
<wd:LOA_End_Date>2018-03-02</wd:LOA_End_Date>
</wd:LeaveDetail>
</wd:Event>
</wd:EventDetails>
</wd:ChangeEvent>
</wd:ChangeEventSummary>
</wd:Census_Report>
I am able to get the LeaveStatus
node into Event
node, but not getting how I can keep each node under LeaveStatus
.
回答1:
Why can't you do simply:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wd="urn:com.workday/bsvc">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="worker" match="wd:Worker_Data" use="wd:EmpID" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="wd:EventDetails">
<xsl:copy>
<xsl:for-each select="key('worker', ../wd:EmpID)/wd:LeaveStatus/wd:LeaveDetail">
<wd:Event>
<xsl:copy-of select="."/>
</wd:Event>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
回答2:
Change your following code (from the second template)
<xsl:copy>
<xsl:apply-templates select="@*"/>
<wd:Event>
<xsl:apply-templates select="$vLeaveStatus/wd:LeaveStatus/wd:LeaveDetail/."/>
</wd:Event>
</xsl:copy>
to
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each select="$vLeaveStatus/wd:LeaveStatus/wd:LeaveDetail">
<wd:Event>
<wd:LeaveDetail>
<xsl:apply-templates select="*"/>
</wd:LeaveDetail>
</wd:Event>
</xsl:for-each>
</xsl:copy>
Then you should get your desired output.
来源:https://stackoverflow.com/questions/56011601/copying-the-child-nodes-of-one-node-into-another-node-but-in-a-separate-node-ba