使用XML将子节点移动到父级别

时间:2015-02-24 14:15:52

标签: xml xslt

我有一个带子节点的XML,我希望它们使用XSL出现在父级节点中。我的XML不是很简单,我对XSL的了解也不是很好。 如果任何人能为我提供解决方案,我会很棒。

我的示例XML如下:

<env:Envelope
  xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
  <env:Body>
    <DPSretrieveResponse
      xmlns="https://tpvs.hmrc.gov.uk/dps">
      <DPSdata
        xmlns="http://www.govtalk.gov.uk/taxation/DPSwrapper/1">
        <DPSheader>
          <Service>PAYE</Service>
          <EntityType>EmpRef</EntityType>          
        </DPSheader>        
        <CodingNoticesP6P6B FormType="P6B" IssueDate="2008-05-06" SequenceNumber="1375" TaxYearEnd="2009"
          xmlns="http://www.govtalk.gov.uk/taxation/CodingNoticesP6P6B/2">
          <EmployerRef>123/A6</EmployerRef>
          <Name>
            <Title>MR</Title>
            <Forename>J V</Forename>
            <Surname>Scanlon</Surname>
          </Name>
          <WorksNumber>SCA/466</WorksNumber>
          <CodingUpdate>
            <TaxCode>NT</TaxCode>
          </CodingUpdate>
        </CodingNoticesP6P6B>
        </DPSdata>
    </DPSretrieveResponse>
  </env:Body>
</env:Envelope>

我需要的是:

<env:Envelope
  xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <env:Body>
    <DPSretrieveResponse
      xmlns="https://tpvs.hmrc.gov.uk/dps">
      <DPSdata
        xmlns="http://www.govtalk.gov.uk/taxation/DPSwrapper/1">
        <DPSheader>
          <Service>PAYE</Service>
          <EntityType>EmpRef</EntityType>          
        </DPSheader>        
        <CodingNoticesP6P6B FormType="P6B" IssueDate="2008-05-06" SequenceNumber="1375" TaxYearEnd="2009"
          xmlns="http://www.govtalk.gov.uk/taxation/CodingNoticesP6P6B/2">
          <EmployerRef>123/A6</EmployerRef>
          <Name>          
          </Name>
          <Title>MR</Title>
          <Forename>J V</Forename>
          <Surname>Scanlon</Surname>
          <WorksNumber>SCA/466</WorksNumber>
          <CodingUpdate>
            <TaxCode>NT</TaxCode>
          </CodingUpdate>
        </CodingNoticesP6P6B>
        </DPSdata>
    </DPSretrieveResponse>
  </env:Body>
</env:Envelope>

简单地说,Name标签下的Title,Forename和Surname需要显示在与Name相同的级别;

<Name>          
</Name>
<Title>MR</Title>
<Forename>J V</Forename>
<Surname>Scanlon</Surname>

非常感谢任何建议。

谢谢。

1 个答案:

答案 0 :(得分:0)

使用标识模板,您可以复制在结果树中不应更改的所有节点:

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

您可以为根节点创建单独的模板以添加额外的命名空间声明:

<xsl:template match="env:Envelope">
    <xsl:copy>
        <xsl:namespace name="xsi" select="'http://www.w3.org/2001/XMLSchema-instance'" />
        <xsl:namespace name="soapenc" select="'http://schemas.xmlsoap.org/soap/encoding/'" />
        <xsl:namespace name="xsd" select="'http://www.w3.org/2001/XMLSchema'" />
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>

最后,要将Name的子项向上移动一级,首先需要声明Name所属的命名空间:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 ... xmlns:ns0="http://www.govtalk.gov.uk/taxation/CodingNoticesP6P6B/2">

因此您可以使用您声明的前缀限定匹配。然后你只需在子节点上调用<apply-templates/>而不复制当前元素:

<xsl:template match="ns0:Name">
     <xsl:apply-templates />
</xsl:template>

这是一个应该有效的完整样式表:

<?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:ns0="http://www.govtalk.gov.uk/taxation/CodingNoticesP6P6B/2"
    exclude-result-prefixes="ns0"
    version="2.0">

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

    <xsl:template match="env:Envelope">
        <xsl:copy>
            <xsl:namespace name="xsi" select="'http://www.w3.org/2001/XMLSchema-instance'" />
            <xsl:namespace name="soapenc" select="'http://schemas.xmlsoap.org/soap/encoding/'" />
            <xsl:namespace name="xsd" select="'http://www.w3.org/2001/XMLSchema'" />
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>

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

    <xsl:template match="ns0:Name">
         <xsl:apply-templates />
    </xsl:template>

</xsl:stylesheet>