XSL Transformation以动态创建XML节点

时间:2018-05-17 22:31:06

标签: xslt

源XML:

<AWARD>
  <FIELD1>XYZ</FIELD1>
  <AWARDLINE>
     <ALINENUM>1</ALINENUM>
     <SHIPMENT>
        <SHIPLINENUM>1.1</SHIPLINENUM>
        <ACCOUNT>
          <ACCOUNTLINENUM>1.1.1</ACCOUNTLINENUM>
          <ASSOCIATEDREQ>
            <AREQNUM>1.1.1.1</AREQNUM>
          </ASSOCIATEDREQ>
        </ACCOUNT>
    </SHIPMENT>     
  </AWARDLINE>   
    <AWARDLINE>
     <ALINENUM>2</ALINENUM>
  </AWARDLINE>     
</AWARD>  

除了AWARD所有子节点&#34; AWARDLINE&#34; ,&#34; SHIPMENT&#34;,&#34; ACCOUNT&#34;,&#34; ASSOCIATEDREQ&#34;可能存在或可能不存在。   如上所示,AWARDLINE 2没有SHIPMENT / ACCOUNT / ASSOCIATEDREQ节点。

所需目标XML

<AWARD>
  <FIELD1>XYZ</FIELD1>
  <AWARDLINE>
     <ALINENUM>1</ALINENUM>
     <SHIPMENT>
        <SHIPLINENUM>1.1</SHIPLINENUM>
        <ACCOUNT>
          <ACCOUNTLINENUM>1.1.1</ACCOUNTLINENUM>
          <ASSOCIATEDREQ>
            <AREQNUM>1.1.1.1</AREQNUM>
          </ASSOCIATEDREQ>
        </ACCOUNT>
    </SHIPMENT>     
  </AWARDLINE>   
  <AWARDLINE>
     <ALINENUM>2</ALINENUM>
     <SHIPMENT> 
       <ACCOUNT>
         </ASSOCIATEDREQ>
       </ACCOUNT>
     </SHIPMENT>
  </AWARDLINE>     
</AWARD>

1 个答案:

答案 0 :(得分:0)

您可以使用此XSLT-1.0替换所有相关节点(如果存在)。它有选择地重建AWARDLINE元素的结构,并与身份模板结合使用。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

  <!-- reconstruction of the AWARDLINE element structure -->
  <xsl:template match="AWARDLINE">
    <xsl:copy>
        <xsl:copy-of select="*[not(self::SHIPMENT)]" />
        <SHIPMENT>
            <xsl:copy-of select="SHIPMENT/*[not(self::ACCOUNT)]" />
            <ACCOUNT>
                <xsl:copy-of select="SHIPMENT/ACCOUNT/*[not(self::ASSOCIATEDREQ)]" />
                <ASSOCIATEDREQ>
                    <xsl:copy-of select="SHIPMENT/ACCOUNT/ASSOCIATEDREQ/*" />
                </ASSOCIATEDREQ>
            </ACCOUNT>
        </SHIPMENT> 
    </xsl:copy>
  </xsl:template>    
</xsl:stylesheet>

另一种可能性是使用模板。这可以处理多个SHIPMENT元素,如果不存在其他元素,则创建空结构。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

  <!-- reconstruction of the AWARDLINE element structure -->
  <xsl:template match="AWARDLINE">
    <xsl:copy>
        <xsl:copy-of select="*[not(self::SHIPMENT)]|@*" />
        <xsl:apply-templates select="SHIPMENT" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="AWARDLINE[not(SHIPMENT)]">
    <xsl:copy>
        <xsl:copy-of select="*|@*" />
        <SHIPMENT>
          <ACCOUNT>
            <ASSOCIATEDREQ />
          </ACCOUNT>
        </SHIPMENT>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="SHIPMENT">
    <xsl:copy>
        <xsl:copy-of select="*[not(self::ACCOUNT)]|@*" />
        <xsl:apply-templates select="ACCOUNT" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="SHIPMENT[not(ACCOUNT)]">  
    <xsl:copy>
        <xsl:copy-of select="*|@*" />
        <ACCOUNT>
          <ASSOCIATEDREQ />
        </ACCOUNT>
    </xsl:copy>   
  </xsl:template>  

  <xsl:template match="ACCOUNT">
    <xsl:copy>
        <xsl:copy-of select="*[not(self::ASSOCIATEDREQ)]|@*" />
        <xsl:apply-templates select="ASSOCIATEDREQ" />
    </xsl:copy>
  </xsl:template>  

  <xsl:template match="ACCOUNT[not(ASSOCIATEDREQ)]">  
    <xsl:copy>
        <xsl:copy-of select="*|@*" />
        <ASSOCIATEDREQ />
    </xsl:copy>   
  </xsl:template>  

  <xsl:template match="ASSOCIATEDREQ">
    <xsl:copy>
        <xsl:copy-of select="*|@*" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>