英文:
Need to delete a child and place the deleted child with same level as parent
问题
我正在寻找一个XSLT代码,用于删除一个子元素并将被删除的子元素与其父级平级放置。请查看以下输入:
<PerPerson>
<PerPerson>
<personIdExternal>employee1</personIdExternal>
<dateOfBirth>1995-05-01T00:00:00.000</dateOfBirth>
<employmentNav>
<EmpEmployment>
<serviceDate/>
<assignmentClass>GA</assignmentClass>
<personIdExternal>employee1</personIdExternal>
<empGlobalAssignmentNav>
<EmpGlobalAssignment>
<BenefitEnrollment>
<effectiveEndDate>2023-06-18T00:00:00.000</effectiveEndDate>
<workerId>90000028</workerId>
</BenefitEnrollment>
<BenefitEnrollment>
<effectiveEndDate>2023-06-19T00:00:00.000</effectiveEndDate>
<workerId>90000028</workerId>
<id>1213CF8537BE4248BE3231A0E4E7226F</id>
</BenefitEnrollment>
<id>1213CF8537BE4248BE3231A0E4E7226F</id>
<assignmentType>131144</assignmentType>
<startDate>2023-05-01T00:00:00.000</startDate>
</EmpGlobalAssignment>
</empGlobalAssignmentNav>
<userId>employee1</userId>
<startDate>2023-05-01T00:00:00.000</startDate>
</EmpEmployment>
<EmpEmployment>
<serviceDate>2023-01-01T00:00:00.000</serviceDate>
<assignmentClass>ST</assignmentClass>
<personIdExternal>employee1</personIdExternal>
<empGlobalAssignmentNav/>
<userId>employee1</userId>
<startDate>2023-01-01T00:00:00.000</startDate>
</EmpEmployment>
</employmentNav>
</PerPerson>
<PerPerson>
<personIdExternal>employee2</personIdExternal>
<dateOfBirth>1988-05-03T00:00:00.000</dateOfBirth>
<employmentNav>
<EmpEmployment>
<serviceDate>2022-01-01T00:00:00.000</serviceDate>
<assignmentClass>ST</assignmentClass>
<personIdExternal>employee2</personIdExternal>
<BenefitEnrollment>
<effectiveEndDate>2023-06-19T00:00:00.000</effectiveEndDate>
<workerId>employee2</workerId>
<id>45B130BDB62D476CB4A95B776BD59B8C</id>
</BenefitEnrollment>
<BenefitEnrollment>
<id>45B130BDB62D476CB4A95B776BD59B8C</id>
</BenefitEnrollment>
<empGlobalAssignmentNav/>
<userId>employee2</userId>
<startDate>2022-01-01T00:00:00.000</startDate>
</EmpEmployment>
</employmentNav>
</PerPerson>
</PerPerson>
对于第一个人,即employee1,BenefitEnrollment子元素位于empGlobalAssignmentNav父元素下,而empGlobalAssignmentNav父元素仅适用于全球员工,这意味着它可能不会总是存在。
对于第二个人,即employee2,BenefitEnrollment子元素位于empemployment父元素下。这是一个本地员工的情况。
我希望输出如下。每当在empGlobalAssignmentNav下存在BenefitEnrollments,我希望将它们生成在父级EmpEmployment下,对于Employee 2,我不需要任何更改,因为Employee 2已经在EmpEmployment下生成。
<PerPerson>
<PerPerson>
<personIdExternal>employee1</personIdExternal>
<dateOfBirth>1995-05-01T00:00:00.000</dateOfBirth>
<employmentNav>
<EmpEmployment>
<serviceDate/>
<assignmentClass>GA</assignmentClass>
<personIdExternal>employee1</personIdExternal>
<BenefitEnrollment>
<effectiveEndDate>2023-06-18T00:00:00.000</effectiveEndDate>
<workerId>90000028</workerId>
</BenefitEnrollment>
<BenefitEnrollment>
<effectiveEndDate>2023-06-19T00:00:00.000</effectiveEndDate>
<workerId>90000028</workerId>
<id>1213CF8537BE4248BE3231A0E4E7226F</id>
</BenefitEnrollment>
<empGlobalAssignmentNav>
<EmpGlobalAssignment>
<id>1213CF8537BE4248BE3231A0E4E7226F</id>
<assignmentType>131144</assignmentType>
<startDate>2023-05-01T00:00:00.000</startDate>
</EmpGlobalAssignment>
</empGlobalAssignmentNav>
<userId>employee1</userId>
<startDate>2023-05-01T00:00:00.000</startDate>
</EmpEmployment>
<EmpEmployment>
<serviceDate>2023-01-01T00:00:00.000</serviceDate>
<assignmentClass>ST</assignmentClass>
<personIdExternal>employee1</personIdExternal>
<empGlobalAssignmentNav/>
<userId>employee1</userId>
<startDate>2023-01-01T00:00:00.000</startDate>
<BenefitEnrollment>
<effectiveEndDate>2023-06-19T00:00:00.000</effectiveEndDate>
<workerId>employee1</workerId>
<id>45B130BDB62D476CB4A95B776BD59B8C</id>
</BenefitEnrollment>
<BenefitEnrollment>
<id>45B130BDB62D476CB4A95B776BD59B8C</id>
</BenefitEnrollment>
</EmpEmployment>
</employmentNav>
</PerPerson>
<PerPerson>
<personIdExternal>employee2</personIdExternal>
<dateOfBirth>1988-05-03T00:00:00.000</dateOfBirth>
<employmentNav>
<EmpEmployment>
<serviceDate>2022-01
<details>
<summary>英文:</summary>
I am looking for a XSLT code to delete a child and place the deleted child with same level as parent. Please find the below input :
<PerPerson>
<PerPerson>
<personIdExternal>employee1</personIdExternal>
<dateOfBirth>1995-05-01T00:00:00.000</dateOfBirth>
<employmentNav>
<EmpEmployment>
<serviceDate/>
<assignmentClass>GA</assignmentClass>
<personIdExternal>employee1</personIdExternal>
<empGlobalAssignmentNav>
<EmpGlobalAssignment>
<BenefitEnrollment>
<effectiveEndDate>2023-06-18T00:00:00.000</effectiveEndDate>
<workerId>90000028</workerId>
</BenefitEnrollment>
<BenefitEnrollment>
<effectiveEndDate>2023-06-19T00:00:00.000</effectiveEndDate>
<workerId>90000028</workerId>
<id>1213CF8537BE4248BE3231A0E4E7226F</id>
</BenefitEnrollment>
<id>1213CF8537BE4248BE3231A0E4E7226F</id>
<assignmentType>131144</assignmentType>
<startDate>2023-05-01T00:00:00.000</startDate>
</EmpGlobalAssignment>
</empGlobalAssignmentNav>
<userId>employee1</userId>
<startDate>2023-05-01T00:00:00.000</startDate>
</EmpEmployment>
<EmpEmployment>
<serviceDate>2023-01-01T00:00:00.000</serviceDate>
<assignmentClass>ST</assignmentClass>
<personIdExternal>employee1</personIdExternal>
<empGlobalAssignmentNav/>
<userId>employee1</userId>
<startDate>2023-01-01T00:00:00.000</startDate>
</EmpEmployment>
</employmentNav>
</PerPerson>
<PerPerson>
<personIdExternal>employee2</personIdExternal>
<dateOfBirth>1988-05-03T00:00:00.000</dateOfBirth>
<employmentNav>
<EmpEmployment>
<serviceDate>2022-01-01T00:00:00.000</serviceDate>
<assignmentClass>ST</assignmentClass>
<personIdExternal>employee2</personIdExternal>
<BenefitEnrollment>
<effectiveEndDate>2023-06-19T00:00:00.000</effectiveEndDate>
<workerId>employee2</workerId>
<id>45B130BDB62D476CB4A95B776BD59B8C</id>
</BenefitEnrollment>
<BenefitEnrollment>
<id>45B130BDB62D476CB4A95B776BD59B8C</id>
</BenefitEnrollment>
<empGlobalAssignmentNav/>
<userId>employee2</userId>
<startDate>2022-01-01T00:00:00.000</startDate>
</EmpEmployment>
</employmentNav>
</PerPerson>
</PerPerson>
Here for the 1st person i.e employee1 the benefitenrollment child is under empGlobalAssignmentNav parent , the empGlobalAssignmentNav parent occurs only for global employees , so that means it may not come always
[![enter image description here][1]][1]
For the 2nd person i.e employee2 the benefitenrollment child is under empemployment parent .This case is for a local employee.
[![enter image description here][2]][2]
I would like to have the output as below . When ever there are benefitenrollments under empGlobalAssignmentNav ie employee 1, I would like those generated at parent level i.e under EmpEmployment , I dont want any change for Employee 2 , as employee 2 is already generating under EmpEmployment.
<PerPerson>
<PerPerson>
<personIdExternal>employee1</personIdExternal>
<dateOfBirth>1995-05-01T00:00:00.000</dateOfBirth>
<employmentNav>
<EmpEmployment>
<serviceDate/>
<assignmentClass>GA</assignmentClass>
<personIdExternal>employee1</personIdExternal>
<BenefitEnrollment>
<effectiveEndDate>2023-06-18T00:00:00.000</effectiveEndDate>
<workerId>90000028</workerId>
</BenefitEnrollment>
<BenefitEnrollment>
<effectiveEndDate>2023-06-19T00:00:00.000</effectiveEndDate>
<workerId>90000028</workerId>
<id>1213CF8537BE4248BE3231A0E4E7226F</id>
</BenefitEnrollment>
<empGlobalAssignmentNav>
<EmpGlobalAssignment>
<id>1213CF8537BE4248BE3231A0E4E7226F</id>
<assignmentType>131144</assignmentType>
<startDate>2023-05-01T00:00:00.000</startDate>
</EmpGlobalAssignment>
</empGlobalAssignmentNav>
<userId>employee1</userId>
<startDate>2023-05-01T00:00:00.000</startDate>
</EmpEmployment>
<EmpEmployment>
<serviceDate>2023-01-01T00:00:00.000</serviceDate>
<assignmentClass>ST</assignmentClass>
<personIdExternal>employee1</personIdExternal>
<empGlobalAssignmentNav/>
<userId>employee1</userId>
<startDate>2023-01-01T00:00:00.000</startDate>
</EmpEmployment>
</employmentNav>
</PerPerson>
<PerPerson>
<personIdExternal>employee2</personIdExternal>
<dateOfBirth>1988-05-03T00:00:00.000</dateOfBirth>
<employmentNav>
<EmpEmployment>
<serviceDate>2022-01-01T00:00:00.000</serviceDate>
<assignmentClass>ST</assignmentClass>
<personIdExternal>employee2</personIdExternal>
<BenefitEnrollment>
<effectiveEndDate>2023-06-19T00:00:00.000</effectiveEndDate>
<workerId>employee2</workerId>
<id>45B130BDB62D476CB4A95B776BD59B8C</id>
</BenefitEnrollment>
<BenefitEnrollment>
<id>45B130BDB62D476CB4A95B776BD59B8C</id>
</BenefitEnrollment>
<empGlobalAssignmentNav/>
<userId>employee2</userId>
<startDate>2022-01-01T00:00:00.000</startDate>
</EmpEmployment>
</employmentNav>
</PerPerson>
</PerPerson>
[![enter image description here][3]][3]
I have tried the XSLT with the below logic, but no luck it is deleting the benefitenrolment child node segment from the empGlobalAssignmentNav and not placing under EmpEmployment
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!-- Identity transform -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="EmpEmployment">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:apply-templates select="../empGlobalAssignmentNav/EmpGlobalAssignment/BenefitEnrollment"/>
</xsl:copy>
</xsl:template>
<xsl:template match="empGlobalAssignmentNav/EmpGlobalAssignment/BenefitEnrollment"/>
</xsl:stylesheet>
Any help is much appreciated.
[1]: https://i.stack.imgur.com/ggGY0.png
[2]: https://i.stack.imgur.com/8kp9P.png
[3]: https://i.stack.imgur.com/Le3S5.png
</details>
# 答案1
**得分**: 1
以下是您要求的部分翻译:
1. 当前上下文是 `EmpEmployment`(因为这是模板匹配的内容,没有任何更改),而 `empGlobalAssignmentNav` 是 `EmpEmployment` 的子元素,所以当您从 `../` 开始选择时,它会上溯到 `EmpEmployment` 的父级,而 `EmpEmployment` 的父级没有 `EmpGlobalAssignmentNav` 子元素。请删除选择中的 `../` 部分。
2. 您有一个模板会删除原始的 `BenefitEnrollment`(`match="empGlobalAssignmentNav/EmpGlobalAssignment/BenefitEnrollment"`),这是正确的,但当您执行 `apply-templates` 时,该模板也会匹配 `BenefitEnrollment`(因为所有匹配都基于输入 XML,而不是输出中的更改)。如果您不需要对这些元素进行额外处理,可以将 `apply-templates` 简单地更改为 `copy-of`。或者,您可以使用 [`mode`][1] 或 [`named template`][2] 而不是制作副本。
3. 最后一个问题是 `apply-templates` 的位置。在您所期望的输出示例中,`BenefitEnrollment` 元素被放置在 `empGlobalAssignmentNav` 之前。而现在它会在 `EmpEmployment` 的末尾输出。我建议您匹配 `empGlobalAssignmentNav` 而不是 `EmpEmployment`。这样,您可以在输出 `empGlobalAssignmentNav` 之前输出 `BenefitEnrollment` 的副本。
示例代码如下:
```xslt
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="empGlobalAssignmentNav[EmpGlobalAssignment/BenefitEnrollment]">
<xsl:copy-of select="EmpGlobalAssignment/BenefitEnrollment"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="empGlobalAssignmentNav/EmpGlobalAssignment/BenefitEnrollment"/>
</xsl:stylesheet>
工作示例链接:http://xsltfiddle.liberty-development.net/jyH7UCV
如果您好奇的话,这是另一种使用模式和命名 identity transform 的选项。
这种方式的好处是,如果我想对这些 BenefitEnrollment
元素进行额外处理,我可以删除 <xsl:call-template name="identity"/>
并执行我需要的任何处理。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="empGlobalAssignmentNav[EmpGlobalAssignment/BenefitEnrollment]">
<xsl:apply-templates select="EmpGlobalAssignment/BenefitEnrollment" mode="keep"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="BenefitEnrollment" mode="keep">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="empGlobalAssignmentNav/EmpGlobalAssignment/BenefitEnrollment"/>
</xsl:stylesheet>
工作示例链接:http://xsltfiddle.liberty-development.net/jyH7UCV/1
英文:
Very close, but you have a few issues with your XSLT attempt and they all have to do with this line:
<xsl:apply-templates select="../empGlobalAssignmentNav/EmpGlobalAssignment/BenefitEnrollment"/>
- The current context is
EmpEmployment
(because that's what the template matches and nothing changes that).empGlobalAssignmentNav
is a child ofEmpEmployment
so when you start your select with../
that goes up to the parent ofEmpEmployment
and it doesn't have aEmpGlobalAssignmentNav
child. Remove the../
from the select. - You have a template that removes the original
BenefitEnrollment
(match="empGlobalAssignmentNav/EmpGlobalAssignment/BenefitEnrollment"
) which is correct but when you do theapply-templates
that template also matches theBenefitEnrollment
(because all matches are based on the input XML; not what you've changed in the output). You can simply changeapply-templates
tocopy-of
if you don't have any additional processing to do on those elements. Alternately you can use amode
or anamed template
instead of a making a copy. - The last issue is the location of the
apply-templates
. In your desired output example, you have theBenefitEnrollment
elements being placed beforeempGlobalAssignmentNav
. Where it would be output now is at the end ofEmpEmployment
. What I would suggest is matchingempGlobalAssignmentNav
instead ofEmpEmployment
. That way you can output the copy of theBenefitEnrollment
before outputtingempGlobalAssignmentNav
.
Example:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="empGlobalAssignmentNav[EmpGlobalAssignment/BenefitEnrollment]">
<xsl:copy-of select="EmpGlobalAssignment/BenefitEnrollment"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="empGlobalAssignmentNav/EmpGlobalAssignment/BenefitEnrollment"/>
</xsl:stylesheet>
Working fiddle: http://xsltfiddle.liberty-development.net/jyH7UCV
If you're curious, here's another option using both mode and naming the identity transform.
The benefit of this is that if I wanted to do additional processing of those BenefitEnrollment
elements, I could remove <xsl:call-template name="identity"/>
and do whatever processing I needed.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="empGlobalAssignmentNav[EmpGlobalAssignment/BenefitEnrollment]">
<xsl:apply-templates select="EmpGlobalAssignment/BenefitEnrollment" mode="keep"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="BenefitEnrollment" mode="keep">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="empGlobalAssignmentNav/EmpGlobalAssignment/BenefitEnrollment"/>
</xsl:stylesheet>
Working fiddle: http://xsltfiddle.liberty-development.net/jyH7UCV/1
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论