【问题标题】:XSLT to flatten specific XML nodesXSLT 展平特定的 XML 节点
【发布时间】:2011-10-13 20:21:59
【问题描述】:

我收到了一个格式如下定义的 XML。我正在编写一些代码来转换 XML,使其只有特定的节点会被展平。

<TransactionRequest>
  <OrderRequests>
    <OrderRequest>
      <ReferenceNumber>1234567</ReferenceNumber>
      <TransactionTime>2010-11-16T00:00:00-08:00</TransactionTime>
      <IsRush>true</IsRush>
      <ShippingAddress>
        <Name>Tom Hanks</Name>
        <Address1>1123 Canada Way</Address1>
        <City>Burnaby</City>
        <Province>BC</Province>
        <PostalCode>V3B13B</PostalCode>
        <HomePhone>6048871121</HomePhone>
        <BusinessPhone>6041232342</BusinessPhone>
      </ShippingAddress>
      <ProgramType>C2</ProgramType>
      <Comments>Deliver to the receptionist</Comments>
      <Items>
        <Item>
          <Sku>UN10004</Sku>
          <Quantity>2</Quantity>
        </Item>
        <Item>
          <Sku>UN980011</Sku>
          <Quantity>1</Quantity>
        </Item>
      </Items>
    </OrderRequest>
  </OrderRequests>
  <TraceRequests>
    <TraceRequest>
      <ReferenceNumber>23432345</ReferenceNumber>
      <TransactionTime>2010-11-16T00:00:00-08:00</TransactionTime>
      <OriginalReferenceNumber>1234567</OriginalReferenceNumber>
      <Comments>Trace Items</Comments>
      <TraceItems>
        <TraceItem>
          <Sku>UN10004</Sku>
          <Quantity>2</Quantity>
          <ShipmentNumber>CM88888990</ShipmentNumber>
        </TraceItem>
        <TraceItem>
          <Sku>UN980011</Sku>
          <ProductCode>AA0091</ProductCode>
          <Quantity>1</Quantity>
          <ShipmentNumber>DDP123123123</ShipmentNumber>
        </TraceItem>
      </TraceItems>
    </TraceRequest>
  </TraceRequests>
</TransactionRequest>

我希望结果看起来像下面的 XML。不同之处在于,在此 XML 中,TraceRequest 节点将被拆分为每个 Items/Item 节点,方法是为每个 Items/Item 复制一次父信息。

<?xml version="1.0"?>
<TransactionRequest>
  <OrderRequests>
    <OrderRequest>
      <ReferenceNumber>1234567</ReferenceNumber>
      <TransactionTime>2010-11-16T00:00:00-08:00</TransactionTime>
      <IsRush>true</IsRush>
      <ShippingAddress>
        <Name>Tom Hanks</Name>
        <Address1>1123 Canada Way</Address1>
        <City>Burnaby</City>
        <Province>BC</Province>
        <PostalCode>V3B13B</PostalCode>
        <HomePhone>6048871121</HomePhone>
        <BusinessPhone>6041232342</BusinessPhone>
      </ShippingAddress>
      <ProgramType>C2</ProgramType>
      <Comments>Deliver to the receptionist</Comments>
      <Items>
        <Item>
          <Sku>UN10004</Sku>
          <Quantity>2</Quantity>
        </Item>
        <Item>
          <Sku>UN980011</Sku>
          <Quantity>1</Quantity>
        </Item>
      </Items>
    </OrderRequest>
  </OrderRequests>
  <TraceRequests>
    <TraceRequest>
      <ReferenceNumber>23432345</ReferenceNumber>
      <TransactionTime>2010-11-16T00:00:00-08:00</TransactionTime>
      <OriginalReferenceNumber>1234567</OriginalReferenceNumber>
      <Comments>Trace Items</Comments>
      <Sku>UN10004</Sku>
      <Quantity>2</Quantity>
      <ShipmentNumber>CM88888990</ShipmentNumber>
    </TraceRequest>
    <TraceRequest>
      <ReferenceNumber>23432345</ReferenceNumber>
      <TransactionTime>2010-11-16T00:00:00-08:00</TransactionTime>
      <OriginalReferenceNumber>1234567</OriginalReferenceNumber>
      <Comments>Trace Items</Comments>
      <Sku>UN980011</Sku>
      <ProductCode>AA0091</ProductCode>
      <Quantity>1</Quantity>
      <ShipmentNumber>DDP123123123</ShipmentNumber>
    </TraceRequest>
  </TraceRequests>
</TransactionRequest>

我似乎无法生成 XSLT 来仅展平 TraceRequest 元素的特定子节点元素。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    您可以通过使用特殊情况的额外模板覆盖标准身份转换来做到这一点。

    首先,当您匹配一个 TraceRequest 节点时,您希望直接跳到匹配的 TraceItem 节点,在那里您将进行复制。在这种情况下,当前的 TraceRequest 节点可以作为参数传入,以便以后复制其子节点。

    <xsl:template match="TraceRequest">
       <xsl:apply-templates select="TraceItems/TraceItem">
          <xsl:with-param name="TraceRequestNode" select="."/>
       </xsl:apply-templates>
    </xsl:template>
    

    然后,在匹配 TraceItem 时,您只需复制通过参数传入的 TraceRequest 的子节点(不包括 TraceItems 节点) ,以及您当前所在的 TraceItem 节点的子节点。

    <xsl:template match="TraceItem">
       <xsl:param name="TraceRequestNode"/>
       <TraceRequest>
          <xsl:apply-templates select="$TraceRequestNode/*[not(self::TraceItems)]"/>
          <xsl:apply-templates select="@*|node()"/>
       </TraceRequest>
    </xsl:template>
    

    所以,给定完整的 XSLT:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:output method="xml" indent="yes" />
    
       <xsl:template match="@*|node()">
          <xsl:copy>
             <xsl:apply-templates select="@*|node()"/>
          </xsl:copy>
       </xsl:template>
    
       <xsl:template match="TraceRequest">
          <xsl:apply-templates select="TraceItems/TraceItem">
             <xsl:with-param name="TraceRequestNode" select="."/>
          </xsl:apply-templates>
       </xsl:template>
    
       <xsl:template match="TraceItem">
          <xsl:param name="TraceRequestNode"/>
          <TraceRequest>
             <xsl:apply-templates select="$TraceRequestNode/*[not(self::TraceItems)]"/>
             <xsl:apply-templates select="@*|node()"/>
          </TraceRequest>
       </xsl:template>
    </xsl:stylesheet>
    

    当应用于您的示例 XML 时,输出如下:

    <TransactionRequest>
       <OrderRequests>
          <OrderRequest>
             <ReferenceNumber>1234567</ReferenceNumber>
             <TransactionTime>2010-11-16T00:00:00-08:00</TransactionTime>
             <IsRush>true</IsRush>
             <ShippingAddress>
                <Name>Tom Hanks</Name>
                <Address1>1123 Canada Way</Address1>
                <City>Burnaby</City>
                <Province>BC</Province>
                <PostalCode>V3B13B</PostalCode>
                <HomePhone>6048871121</HomePhone>
                <BusinessPhone>6041232342</BusinessPhone>
             </ShippingAddress>
             <ProgramType>C2</ProgramType>
             <Comments>Deliver to the receptionist</Comments>
             <Items>
                <Item>
                   <Sku>UN10004</Sku>
                   <Quantity>2</Quantity>
                </Item>
                <Item>
                   <Sku>UN980011</Sku>
                   <Quantity>1</Quantity>
                </Item>
             </Items>
          </OrderRequest>
       </OrderRequests>
       <TraceRequests>
          <TraceRequest>
             <ReferenceNumber>23432345</ReferenceNumber>
             <TransactionTime>2010-11-16T00:00:00-08:00</TransactionTime>
             <OriginalReferenceNumber>1234567</OriginalReferenceNumber>
             <Comments>Trace Items</Comments>
             <Sku>UN10004</Sku>
             <Quantity>2</Quantity>
             <ShipmentNumber>CM88888990</ShipmentNumber>
          </TraceRequest>
          <TraceRequest>
             <ReferenceNumber>23432345</ReferenceNumber>
             <TransactionTime>2010-11-16T00:00:00-08:00</TransactionTime>
             <OriginalReferenceNumber>1234567</OriginalReferenceNumber>
             <Comments>Trace Items</Comments>
             <Sku>UN980011</Sku>
             <ProductCode>AA0091</ProductCode>
             <Quantity>1</Quantity>
             <ShipmentNumber>DDP123123123</ShipmentNumber>
          </TraceRequest>
       </TraceRequests>
    </TransactionRequest>
    

    【讨论】:

      【解决方案2】:

      好的,我想我在下面运行 XSLT 时回答了我自己的问题:

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      
        <xsl:template match="TransactionRequest">
          <TransactionRequest>
            <xsl:copy-of select="OrderRequests"/>
            <TraceRequests>
              <xsl:for-each select="TraceRequests/TraceRequest/TraceItems/TraceItem">
                <TraceRequest>
                  <xsl:copy-of select="../../ReferenceNumber"/>
                  <xsl:copy-of select="../../TransactionTime"/>
                  <xsl:copy-of select="../../OriginalReferenceNumber"/>
                  <xsl:copy-of select="../../Comments"/>
      
                  <xsl:copy-of select="Sku"/>
                  <xsl:copy-of select="Quantity"/>
                  <xsl:copy-of select="ShipmentNumber"/>
                  <xsl:copy-of select="ProductCode"/>
                  <xsl:copy-of select="DropShipPoNumber"/>
                </TraceRequest>
              </xsl:for-each>
            </TraceRequests>
         </TransactionRequest>
        </xsl:template>
      </xsl:stylesheet>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多