【问题标题】:How to combine all children of two peers into one XML node?如何将两个对等节点的所有子节点合并到一个 XML 节点中?
【发布时间】:2020-05-28 15:05:49
【问题描述】:

我将三个 XML 文件合并为一个,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Root>
    <wd:Report_Data xmlns:wd="urn:com.workday/bsvc">
        <wd:Report_Entry>
            <wd:RBO_Group>
                <wd:Comment_BatchID>kns_timeoff20200105_5365_78659138</wd:Comment_BatchID>
                <wd:Date_Worked>2020-01-02</wd:Date_Worked>
                <wd:Hours>9</wd:Hours>
                <wd:Type>Vacation</wd:Type>
                <wd:Process_Date>2020-02-10</wd:Process_Date>
            </wd:RBO_Group>
            <wd:Employee_ID>106060</wd:Employee_ID>
        </wd:Report_Entry>
    </wd:Report_Data>
    <wd:Report_Data xmlns:wd="urn:com.workday/bsvc">
        <wd:Report_Entry>
            <wd:RBO_Group>
                <wd:Date_Worked>2014-12-15</wd:Date_Worked>
                <wd:Hours>41.53</wd:Hours>
                <wd:Type>UNITWAY</wd:Type>
                <wd:Process_Date>2019-09-20</wd:Process_Date>
            </wd:RBO_Group>
            <wd:RBO_Group>
                <wd:Date_Worked>2019-08-04</wd:Date_Worked>
                <wd:Hours>5065.84</wd:Hours>
                <wd:Type>zzzdnu BEREAVEWK2</wd:Type>
                <wd:Process_Date>2019-09-24</wd:Process_Date>
            </wd:RBO_Group>
        </wd:Report_Entry>
    </wd:Report_Data>
    <Data>
        <Worker>
            <INT_ID>228606</INT_ID>
            <WD_BATCH_ID>kns_timeoff20191229_232_78652526</WD_BATCH_ID>
            <WD_PAY_INPUT_ID>228602</WD_PAY_INPUT_ID>
            <DATE_WORKED>2019-12-12</DATE_WORKED>
            <EMPLOYEE_ID>146379</EMPLOYEE_ID>
            <WEEK_END_DATE>2019-12-15</WEEK_END_DATE>
            <EFFECTIVE_DATE>2019-12-29</EFFECTIVE_DATE>
            <HOURS>8</HOURS>
            <PAY_COMPONENT>Jury Duty</PAY_COMPONENT>
            <TK_COMMENTS>kns_wd20191229_232_78652526</TK_COMMENTS>
            <SS_REQUEST_ID>78652508</SS_REQUEST_ID>
            <REQUEST_ID>78652526</REQUEST_ID>
            <PROCESS_DATE>2/6/2020 20:57</PROCESS_DATE>
            <PROCESS_STATUS>C</PROCESS_STATUS>
        </Worker>
    </Data>
</Root>

我想合并两个&lt;wd:Report_Data&gt; 节点的所有子节点,以便它们都在同一个&lt;wd:Report_Data&gt; 节点下。像这样:

<?xml version="1.0" encoding="utf-8"?>
<Root>
    <wd:Report_Data xmlns:wd="urn:com.workday/bsvc">
        <wd:Report_Entry>
            <wd:RBO_Group>
                <wd:Comment_BatchID>kns_timeoff20200105_5365_78659138</wd:Comment_BatchID>
                <wd:Date_Worked>2020-01-02</wd:Date_Worked>
                <wd:Hours>9</wd:Hours>
                <wd:Type>Vacation</wd:Type>
                <wd:Process_Date>2020-02-10</wd:Process_Date>
            </wd:RBO_Group>
            <wd:Employee_ID>106060</wd:Employee_ID>
        </wd:Report_Entry>
        <wd:Report_Entry>
            <wd:RBO_Group>
                <wd:Date_Worked>2014-12-15</wd:Date_Worked>
                <wd:Hours>41.53</wd:Hours>
                <wd:Type>UNITWAY</wd:Type>
                <wd:Process_Date>2019-09-20</wd:Process_Date>
            </wd:RBO_Group>
            <wd:RBO_Group>
                <wd:Date_Worked>2019-08-04</wd:Date_Worked>
                <wd:Hours>5065.84</wd:Hours>
                <wd:Type>zzzdnu BEREAVEWK2</wd:Type>
                <wd:Process_Date>2019-09-24</wd:Process_Date>
            </wd:RBO_Group>
        </wd:Report_Entry>
    </wd:Report_Data>
    <Data>
        <Worker>
            <INT_ID>228606</INT_ID>
            <WD_BATCH_ID>kns_timeoff20191229_232_78652526</WD_BATCH_ID>
            <WD_PAY_INPUT_ID>228602</WD_PAY_INPUT_ID>
            <DATE_WORKED>2019-12-12</DATE_WORKED>
            <EMPLOYEE_ID>146379</EMPLOYEE_ID>
            <WEEK_END_DATE>2019-12-15</WEEK_END_DATE>
            <EFFECTIVE_DATE>2019-12-29</EFFECTIVE_DATE>
            <HOURS>8</HOURS>
            <PAY_COMPONENT>Jury Duty</PAY_COMPONENT>
            <TK_COMMENTS>kns_wd20191229_232_78652526</TK_COMMENTS>
            <SS_REQUEST_ID>78652508</SS_REQUEST_ID>
            <REQUEST_ID>78652526</REQUEST_ID>
            <PROCESS_DATE>2/6/2020 20:57</PROCESS_DATE>
            <PROCESS_STATUS>C</PROCESS_STATUS>
        </Worker>
    </Data>
</Root>

但重要的是 Data 节点保持独立。我复制这个 XML 的最简单方法是什么,只需删除这两行,以便所有“wd:Report_Entry”都在同一个节点下?

我试过了:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wd="urn:com.workday/bsvc">
    <xsl:output method="xml" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*" />

    <!-- Identity template -->
    <xsl:template match="node()|@*">
        <xsl:copy>
             <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="wd:Report_Data/wd:Report_Entry">
           <xsl:copy-of select="//wd:Report_Entry"/>
    </xsl:template>
</xsl:stylesheet>

...几乎可以工作。它将所有 Report_Entry 节点放在同一个父节点下,但它复制了第二个 Report_Entry 节点及其所有子节点。似乎我应该能够使用[1] 限定选择,但我不知道如何进行选择,以应用模板,而不使用默认模板拾取第二个 Report_Data 节点...

有什么建议吗?

【问题讨论】:

  • 您显示的输出与您的描述不符。
  • 好收获。粘贴后忘记编辑了。现在应该是正确的。

标签: xml xslt


【解决方案1】:

我相信最简单的方法是:

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:template match="/Root">
    <xsl:copy>
        <wd:Report_Data>
             <xsl:copy-of select="wd:Report_Data/wd:Report_Entry"/>
        </wd:Report_Data>
        <xsl:copy-of select="Data"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

输出不是你显示的 - 但它是你描述的。

【讨论】:

  • 这行得通,但我不明白为什么select="wd:Report_Data/wd:Report_Entry" 会选择父母双方的所有wd:Report_Entry 节点。我的意思是,答案是“因为 XPath 就是这样工作的”,但这不是我所期望的……是时候学习更多了
  • 因为只选择一个父节点的 wd:Report_Entry 节点,您必须指定哪个父节点 - 例如:select="wd:Report_Data[1]/wd:Report_Entry"
【解决方案2】:

请测试此代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wd="urn:com.workday/bsvc">
    <xsl:output method="xml" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*" />
    <xsl:output indent="true"></xsl:output>
    <!-- Identity template -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="wd:Report_Data/wd:Report_Entry[not(preceding::wd:Report_Entry)]">
        <xsl:copy-of select="//wd:Report_Entry"/>
    </xsl:template>

    <xsl:template match="wd:Report_Entry"/>
</xsl:stylesheet>

【讨论】:

  • 这个答案需要更多描述。
猜你喜欢
  • 2013-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-04
  • 2020-01-21
相关资源
最近更新 更多