首页 > 解决方案 > 需要将所有兄弟姐妹的 XML 文档转换为带有父/子组的 XML

问题描述

我是 XSLT 的新手。我有一个从 Web 服务返回的 XML 响应文档,其中包含每个后缀的标头 (Result_HEADER) 以及标头下方该后缀的事务详细信息(Result_Y 和 Result_Addendum)。标头和事务元素都在响应 XML 中作为同级元素。这是原始的 XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <Peak mlns="http://peak.company.com"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <OffTime>
      <CommandRs>
          <ResponseHeader>
              <Status>
                  <StatusCode>00</StatusCode>
                  <StatusDesc>SUCCESSFUL</StatusDesc>
              </Status>
          </ResponseHeader>
          <AHINRs>
              <Result_HEADER>
                  <Identifier>HEADER</Identifier>
                  <Account>11111111</Account>
                  <Suffix>0</Suffix>
                  <Name>JohnDoe</Name>
                  <FinancialInstitutionDt>44444444</FinancialInstitutionDt>
                  <BranchID>3</BranchID>
              </Result_HEADER>
                     <Identifier>HEADER</Identifier>
                <Account>11111111</Account>
                <Suffix>0</Suffix>
                <Name>JohnDoe</Name>
                <FinancialInstitutionDt>44444444</FinancialInstitutionDt>
                <BranchID>3</BranchID>
            </Result_HEADER>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2734</ID>
                <BatchID>0312</BatchID>
                <TraceID>6355577</TraceID>
                <EffectiveDt>20180411</EffectiveDt>
                <PostingCode>DS</PostingCode>
                <TransactionType>AE</TransactionType>
                <Amount>-45400</Amount>
                <Group>8888</Group>
                <Command>ACHP</Command>
                <ReturnCode />
                <Status>POSTED</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>USAA.COM PAYMNT</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>CREDIT CRD</Description>
            </Result_Y>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2735</ID>
                <BatchID>0312</BatchID>
                <TraceID>6355577</TraceID>
                <EffectiveDt>20180411</EffectiveDt>
                <PostingCode>DS</PostingCode>
                <TransactionType>AE</TransactionType>
                <Amount>-45400</Amount>
                <Group>8888</Group>
                <Command>ACHP</Command>
                <ReturnCode />
                <Status>POSTED</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>USAA.COM PAYMNT</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>CREDIT CRD</Description>
            </Result_Y>                
            <Result_HEADER>
                <Identifier>HEADER</Identifier>
                <Account>11111111</Account>
                <Suffix>2</Suffix>
                <Name>JohnDoe</Name>
                <FinancialInstitutionDt>44444444</FinancialInstitutionDt>
                <BranchID>3</BranchID>
            </Result_HEADER>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2687</ID>
                <BatchID>0207</BatchID>
                <TraceID>3362157</TraceID>
                <EffectiveDt>020180301</EffectiveDt>
                <PostingCode>PA</PostingCode>
                <TransactionType />
                <Amount>93741</Amount>
                <Group>1017</Group>
                <Command>PTDD</Command>
                <ReturnCode />
                <Status>PENDING</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>VACP TREAS 310</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>XXVA BENEF</Description>
            </Result_Y>
            <Result_ARADDENDUM>
                <OutputType>ARADDENDUM</OutputType>
                <ACHAddendum>REF*48*VA COMPENSATION *02/01/18-02/28/18 \</ACHAddendum>
            </Result_ARADDENDUM>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2695</ID>
                <BatchID>0646</BatchID>
                <TraceID>0144778</TraceID>
                <EffectiveDt>20180301</EffectiveDt>
                <PostingCode>PA</PostingCode>
                <TransactionType />
                <Amount>236594</Amount>
                <Group>1014</Group>
                <Command>PTDD</Command>
                <ReturnCode />
                <Status>PENDING</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>DFAS-CLEVELAND</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>RET NET</Description>
            </Result_Y>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2725</ID>
                <BatchID>0597</BatchID>
                <TraceID>3366249</TraceID>
                <EffectiveDt>20180330</EffectiveDt>
                <PostingCode>PA</PostingCode>
                <TransactionType />
                <Amount>93741</Amount>
                <Group>1017</Group>
                <Command>PTDD</Command>
                <ReturnCode />
                <Status>PENDING</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>VACP TREAS 310</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>XXVA BENEF</Description>
            </Result_Y>
            <Result_ARADDENDUM>
                <OutputType>ARADDENDUM</OutputType>
                <ACHAddendum>REF*48*VA COMPENSATION *03/01/18-03/31/18 \</ACHAddendum>
            </Result_ARADDENDUM>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2734</ID>
                <BatchID>0312</BatchID>
                <TraceID>6355577</TraceID>
                <EffectiveDt>20180411</EffectiveDt>
                <PostingCode>DS</PostingCode>
                <TransactionType>AE</TransactionType>
                <Amount>-45400</Amount>
                <Group>8888</Group>
                <Command>ACHP</Command>
                <ReturnCode />
                <Status>POSTED</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>USAA.COM PAYMNT</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>CREDIT CRD</Description>
            </Result_Y>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2735</ID>
                <BatchID>0312</BatchID>
                <TraceID>6355577</TraceID>
                <EffectiveDt>20180411</EffectiveDt>
                <PostingCode>DS</PostingCode>
                <TransactionType>AE</TransactionType>
                <Amount>-45400</Amount>
                <Group>8888</Group>
                <Command>ACHP</Command>
                <ReturnCode />
                <Status>POSTED</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>USAA.COM PAYMNT</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>CREDIT CRD</Description>
            </Result_Y>
            <Result_HEADER>
                <Identifier>HEADER</Identifier>
                <Account>11111111</Account>
                <Suffix>3</Suffix>
                <Name>JohnDoe</Name>
                <FinancialInstitutionDt>44444444</FinancialInstitutionDt>
                <BranchID>3</BranchID>
            </Result_HEADER>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2732</ID>
                <BatchID>0911</BatchID>
                <TraceID>6314883</TraceID>
                <EffectiveDt>20180403</EffectiveDt>
                <PostingCode>DS</PostingCode>
                <TransactionType>AE</TransactionType>
                <Amount>-18638</Amount>
                <Group>8888</Group>
                <Command>ACHP</Command>
                <ReturnCode />
                <Status>PENDING</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>VERIZON</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>PAYMENTREC</Description>
            </Result_Y>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2732</ID>
                <BatchID>1751</BatchID>
                <TraceID>3553385</TraceID>
                <EffectiveDt>20180403</EffectiveDt>
                <PostingCode>PA</PostingCode>
                <TransactionType />
                <Amount>119391</Amount>
                <Group>8888</Group>
                <Command>PTDD</Command>
                <ReturnCode />
                <Status>PENDING</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>CONCUR</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>EXPENSE</Description>
            </Result_Y>
            <Result_ARADDENDUM>
                <OutputType>ARADDENDUM</OutputType>
                <ACHAddendum>Flight home for Ethridge</ACHAddendum>
            </Result_ARADDENDUM>
            <Result_Y>
                <DetailFlag>Y</DetailFlag>
                <ID>2732</ID>
                <BatchID>1751</BatchID>
                <TraceID>3553387</TraceID>
                <EffectiveDt>20180403</EffectiveDt>
                <PostingCode>PA</PostingCode>
                <TransactionType />
                <Amount>61500</Amount>
                <Group>8888</Group>
                <Command>PTDD</Command>
                <ReturnCode />
                <Status>PENDING</Status>
                <TypeCode>RC</TypeCode>
                <CompanyName>CONCUR</CompanyName>
                <CompanyID>1234567890</CompanyID>
                <Description>EXPENSE</Description>
            </Result_Y>
            <Result_ARADDENDUM>
                <OutputType>ARADDENDUM</OutputType>
                <ACHAddendum>Flight to CRC to Williams</ACHAddendum>
            </Result_ARADDENDUM>
          </AHINRs>
        </CommandRs>
     </OffTime>
   </Peak>

我需要能够重组文档,以便每个 Header 元素都包含一个 Results 元素,其中包含该标头的事务详细信息,这里是所需的 XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <Peak xmlns="http://peak.company.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <OffTime>
        <CommandRs>
          <ResponseHeader>
            <Status>
              <StatusCode>00</StatusCode>
              <StatusDesc>SUCCESSFUL</StatusDesc>
            </Status>
          </ResponseHeader>
          <AHINRs>
            <Result_HEADER>
                <Identifier>HEADER</Identifier>
                <Account>11111111</Account>
                <Suffix>0</Suffix>
                <Name>JohnDoe</Name>
                <FinancialInstitutionDt>44444444</FinancialInstitutionDt>
                <BranchID>3</BranchID>
                <Results>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2734</ID>
                        <BatchID>0312</BatchID>
                        <TraceID>6355577</TraceID>
                        <EffectiveDt>20180411</EffectiveDt>
                        <PostingCode>DS</PostingCode>
                        <TransactionType>AE</TransactionType>
                        <Amount>-45400</Amount>
                        <Group>8888</Group>
                        <Command>ACHP</Command>
                        <ReturnCode />
                        <Status>POSTED</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>USAA.COM PAYMNT</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>CREDIT CRD</Description>
                    </Result_Y>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2735</ID>
                        <BatchID>0312</BatchID>
                        <TraceID>6355577</TraceID>
                        <EffectiveDt>20180411</EffectiveDt>
                        <PostingCode>DS</PostingCode>
                        <TransactionType>AE</TransactionType>
                        <Amount>-45400</Amount>
                        <Group>8888</Group>
                        <Command>ACHP</Command>
                        <ReturnCode />
                        <Status>POSTED</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>USAA.COM PAYMNT</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>CREDIT CRD</Description>
                    </Result_Y>                
                </Results>
           </Result_HEADER>
            <Result_HEADER>
                <Identifier>HEADER</Identifier>
                <Account>11111111</Account>
                <Suffix>2</Suffix>
                <Name>JohnDoe</Name>
                <FinancialInstitutionDt>44444444</FinancialInstitutionDt>
                <BranchID>3</BranchID>
                </Results>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2687</ID>
                        <BatchID>0207</BatchID>
                        <TraceID>3362157</TraceID>
                        <EffectiveDt>020180301</EffectiveDt>
                        <PostingCode>PA</PostingCode>
                        <TransactionType />
                        <Amount>93741</Amount>
                        <Group>1017</Group>
                        <Command>PTDD</Command>
                        <ReturnCode />
                        <Status>PENDING</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>VACP TREAS 310</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>XXVA BENEF</Description>
                    </Result_Y>
                    <Result_ARADDENDUM>
                        <OutputType>ARADDENDUM</OutputType>
                        <ACHAddendum>REF*48*VA COMPENSATION *02/01/18-02/28/18 \</ACHAddendum>
                    </Result_ARADDENDUM>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2695</ID>
                        <BatchID>0646</BatchID>
                        <TraceID>0144778</TraceID>
                        <EffectiveDt>20180301</EffectiveDt>
                        <PostingCode>PA</PostingCode>
                        <TransactionType />
                        <Amount>236594</Amount>
                        <Group>1014</Group>
                        <Command>PTDD</Command>
                        <ReturnCode />
                        <Status>PENDING</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>DFAS-CLEVELAND</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>RET NET</Description>
                    </Result_Y>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2725</ID>
                        <BatchID>0597</BatchID>
                        <TraceID>3366249</TraceID>
                        <EffectiveDt>20180330</EffectiveDt>
                        <PostingCode>PA</PostingCode>
                        <TransactionType />
                        <Amount>93741</Amount>
                        <Group>1017</Group>
                        <Command>PTDD</Command>
                        <ReturnCode />
                        <Status>PENDING</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>VACP TREAS 310</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>XXVA BENEF</Description>
                    </Result_Y>
                    <Result_ARADDENDUM>
                        <OutputType>ARADDENDUM</OutputType>
                        <ACHAddendum>REF*48*VA COMPENSATION *03/01/18-03/31/18 \</ACHAddendum>
                    </Result_ARADDENDUM>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2734</ID>
                        <BatchID>0312</BatchID>
                        <TraceID>6355577</TraceID>
                        <EffectiveDt>20180411</EffectiveDt>
                        <PostingCode>DS</PostingCode>
                        <TransactionType>AE</TransactionType>
                        <Amount>-45400</Amount>
                        <Group>8888</Group>
                        <Command>ACHP</Command>
                        <ReturnCode />
                        <Status>POSTED</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>USAA.COM PAYMNT</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>CREDIT CRD</Description>
                    </Result_Y>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2735</ID>
                        <BatchID>0312</BatchID>
                        <TraceID>6355577</TraceID>
                        <EffectiveDt>20180411</EffectiveDt>
                        <PostingCode>DS</PostingCode>
                        <TransactionType>AE</TransactionType>
                        <Amount>-45400</Amount>
                        <Group>8888</Group>
                        <Command>ACHP</Command>
                        <ReturnCode />
                        <Status>POSTED</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>USAA.COM PAYMNT</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>CREDIT CRD</Description>
                    </Result_Y>
                </Results>
            </Result_HEADER>
            <Result_HEADER>
                <Identifier>HEADER</Identifier>
                <Account>11111111</Account>
                <Suffix>3</Suffix>
                <Name>JohnDoe</Name>
                <FinancialInstitutionDt>44444444</FinancialInstitutionDt>
                <BranchID>3</BranchID>
                <Results>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2732</ID>
                        <BatchID>0911</BatchID>
                        <TraceID>6314883</TraceID>
                        <EffectiveDt>20180403</EffectiveDt>
                        <PostingCode>DS</PostingCode>
                        <TransactionType>AE</TransactionType>
                        <Amount>-18638</Amount>
                        <Group>8888</Group>
                        <Command>ACHP</Command>
                        <ReturnCode />
                        <Status>PENDING</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>VERIZON</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>PAYMENTREC</Description>
                    </Result_Y>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2732</ID>
                        <BatchID>1751</BatchID>
                        <TraceID>3553385</TraceID>
                        <EffectiveDt>20180403</EffectiveDt>
                        <PostingCode>PA</PostingCode>
                        <TransactionType />
                        <Amount>119391</Amount>
                        <Group>8888</Group>
                        <Command>PTDD</Command>
                        <ReturnCode />
                        <Status>PENDING</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>CONCUR</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>EXPENSE</Description>
                    </Result_Y>
                    <Result_ARADDENDUM>
                        <OutputType>ARADDENDUM</OutputType>
                        <ACHAddendum>Flight home for Ethridge</ACHAddendum>
                    </Result_ARADDENDUM>
                    <Result_Y>
                        <DetailFlag>Y</DetailFlag>
                        <ID>2732</ID>
                        <BatchID>1751</BatchID>
                        <TraceID>3553387</TraceID>
                        <EffectiveDt>20180403</EffectiveDt>
                        <PostingCode>PA</PostingCode>
                        <TransactionType />
                        <Amount>61500</Amount>
                        <Group>8888</Group>
                        <Command>PTDD</Command>
                        <ReturnCode />
                        <Status>PENDING</Status>
                        <TypeCode>RC</TypeCode>
                        <CompanyName>CONCUR</CompanyName>
                        <CompanyID>1234567890</CompanyID>
                        <Description>EXPENSE</Description>
                    </Result_Y>
                    <Result_ARADDENDUM>
                        <OutputType>ARADDENDUM</OutputType>
                        <ACHAddendum>Flight to CRC to Williams</ACHAddendum>
                    </Result_ARADDENDUM>
                </Results>
            </Result_HEADER>
          </AHINRs>
        </CommandRs>
     </OffTime>
   </Peak>

我已经能够使用显示的 XSL 创建标题并将结果元素添加到每个标题。我无法弄清楚如何在正确的结果元素中选择和插入属于每个标题的事务作为子项:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="2.0" xmlns:fn="http://peak.company.com" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <xsl:apply-templates select="fn:Peak"/>
    </xsl:template>
    <xsl:template match="fn:Peak">
        <xsl:copy select=".">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="fn:OffTime"/>
        </xsl:copy>
</xsl:template>
<xsl:template match="fn:OffTime">
    <xsl:copy select=".">
        <xsl:apply-templates select="fn:CommandRs"/>
    </xsl:copy>
    </xsl:template>
    <xsl:template match="fn:CommandRs">
        <xsl:copy select=".">
            <xsl:apply-templates select="fn:ResponseHeader"/>
            <xsl:apply-templates select="fn:AHINRs"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="fn:ResponseHeader">
        <xsl:copy-of select="."/>
    </xsl:template>
    <xsl:template match="fn:AHINRs">
        <xsl:copy select=".">
            <xsl:apply-templates select="fn:Result_HEADER"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="fn:Result_HEADER">
        <xsl:if test="position() = last()">
            <xsl:call-template name="copy-children"/>
            <xsl:element name="Results" namespace="http://peak.company.com"/>
        </xsl:if>
        <xsl:if test="position() != last()">
            <xsl:call-template name="copy-children"/>
            <xsl:element name="Results" namespace="http://peak.company.com"/>
        </xsl:if>
    </xsl:template>
    <!-- Copy the children of the current node. -->
    <xsl:template name="copy-children">
        <xsl:copy-of select="./*"/>
    </xsl:template>
</xsl:stylesheet>

帮助将不胜感激!

标签: xmlxslt

解决方案


我认为,假设 XSLT 2 或 3,您希望xsl:for-each-group select="*" group-starting-with="Result_HEADER"在模板匹配的上下文中应用AHINRs

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:template match="AHINRs">
        <xsl:copy>
            <xsl:for-each-group select="*" group-starting-with="Result_HEADER">
                <xsl:copy>
                    <xsl:apply-templates/>
                    <Results>
                        <xsl:apply-templates select="current-group() except ."/>
                    </Results>
                </xsl:copy>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bFDb2BW有一个工作演示,如果您与 XSLT 2 相关联,请将其替换xsl:mode为身份转换模板。

同样仔细观察,您的元素似乎应该位于该名称空间中(尽管发布的示例没有正确的名称空间声明),因此在您的真实代码中,您可能希望使用 XSLT 启动

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    xpath-default-namespace="http://peak.company.com"
    xmlns="http://peak.company.com"
    version="3.0">

考虑命名空间。


推荐阅读