从下到上替换xml节点

时间:2015-03-09 22:46:41

标签: xml xslt

嗨我有一个包含2个相等节点的xml。我将替换位于顶部的第一个节点与底部的节点,并删除第二个节点。这两个节点名为“ApplicationArea”并包含子节点。现在第二个节点包含我需要在顶部替换并从底部的xml中删除的原始信息

我的xml是

<SyncShipment versionID="2.6.3" Release="9.2">
<ApplicationArea>
<Sender>
<LogicalID>lid://infor.dbconnector</LogicalID>
<ComponentID>Visual</ComponentID>
<ConfirmationCode>OnError</ConfirmationCode>
</Sender>
<CreationDateTime>2015-03-04T09:25:12.107Z</CreationDateTime>
<BODID>infor-nid:infor:Shipper~S14-01709:?Shipment&verb=Sync</BODID>
</ApplicationArea>
<DataArea>
<Sync>
<TenantID>infor</TenantID>
<AccountingEntityID>NKFEX</AccountingEntityID>
<LocationID>Site~Gouda</LocationID>
<ActionCriteria>
<ActionExpression actionCode="Add"/>
</ActionCriteria>
</Sync>
<Shipment>
<ShipmentHeader>
<DocumentID>Shipper~S14-01709</DocumentID>
<UserArea>
<Property>
<NameValue type="String" name="UDF1">external info</NameValue>
</Property>
<Property>
<NameValue type="xml" name="sourceAA">
<ApplicationArea>
<Sender>
<LogicalID schemeVersionID="VMSHPENT:7.0.0.156:AC7726D2">lid://infor.visual.visual</Logical ID>
<ComponentID>Visual</ComponentID>
<ConfirmationCode>OnError</ConfirmationCode>
</Sender>
<CreationDateTime>2015-03-04T09:25:12.107Z</CreationDateTime>
<BODID schemeAgencyName="Visual" location="Site~Gouda">infor-nid:infor:NKFEX:Site~Gouda:Shipper~S14-01709~1:?Shipment&verb=Sync</BODID>
</ApplicationArea>
</NameValue>
</Property>
</UserArea>
</ShipmentHeader>
<ShipmentItem>
<ItemID>pippo</ItemID>
</ShipmentItem>
</Shipment>
</DataArea>
</SyncShipment>
改造后它应该是这样的

<SyncShipment versionID="2.6.3" Release="9.2">
<ApplicationArea>
<Sender>
<LogicalID schemeVersionID="VMSHPENT:7.0.0.156:AC7726D2">lid://infor.visual.visual</LogicalID>
<ComponentID>Visual</ComponentID>
<ConfirmationCode>OnError</ConfirmationCode>
</Sender>
<CreationDateTime>2015-03-04T09:25:12.107Z</CreationDateTime>
<BODID schemeAgencyName="Visual" location="Site~Gouda">infor-nid:infor:NKFEX:Site~Gouda:Shipper~S14-01709~1:?Shipment&verb=Sync</BODID>
</ApplicationArea>
<DataArea>
<Sync>
<TenantID>infor</TenantID>
<AccountingEntityID>NKFEX</AccountingEntityID>
<LocationID>Site~Gouda</LocationID>
<ActionCriteria>
<ActionExpression actionCode="Add"/>
</ActionCriteria>
</Sync>
<Shipment>
<ShipmentHeader>
<DocumentID>Shipper~S14-01709</DocumentID>
<UserArea>
<Property>
<NameValue type="String" name="UDF1">external info</NameValue>
</Property>
</UserArea>
</ShipmentHeader>
<ShipmentItem>
<ItemID>pippo</ItemID>
</ShipmentItem>
</Shipment>
</DataArea>
</SyncShipment>
你能帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

这是一个关于如何使用XSLT执行此操作的示例。我正在使用所谓的推送方法。这意味着我正在使用xsl:apply-templates来推送数据并允许模板根据需要进行匹配。

此XSLT中最重要的模板是identity transform。它按原样复制所有属性和节点(文本,元素,注释和处理指令)。

我用2个其他模板覆盖了身份转换。一个用于SyncShipment,一个用于Property

SyncShipment匹配的模板会输出SyncShipment元素的副本,然后执行3 xsl:apply-templates来推送我们想要的数据:

  • 当前上下文的属性(SyncShipment
  • ApplicationArea
  • 的后代DataArea
  • 不是ApplicationArea的任何其他节点(这意味着第一个ApplicationArea将不会被处理)

我们在这里使用3个不同的xsl:apply-templates,以便我们获得我们想要的订单。 XSLT中有一条注释显示了如何在XSLT 2.0中更轻松地完成此操作。如果订单根本不重要,您也可以使用此订单而不是三个xsl:apply-templates

<xsl:apply-templates select="@*|DataArea//ApplicationArea|node()[not(self::ApplicationArea)]"/>

匹配Property的模板仅匹配有孩子Property的{​​{1}}个孩子NameValue。模板为空,因此不再进行进一步处理。 (没有输出。)

以下是示例:

XML (更正为well-formed

ApplicationArea

<强> XSLT

<SyncShipment versionID="2.6.3" Release="9.2">
    <ApplicationArea>
        <Sender>
            <LogicalID>lid://infor.dbconnector</LogicalID>
            <ComponentID>Visual</ComponentID>
            <ConfirmationCode>OnError</ConfirmationCode>
        </Sender>
        <CreationDateTime>2015-03-04T09:25:12.107Z</CreationDateTime>
        <BODID>infor-nid:infor:Shipper~S14-01709:?Shipment&amp;verb=Sync</BODID>
    </ApplicationArea>
    <DataArea>
        <Sync>
            <TenantID>infor</TenantID>
            <AccountingEntityID>NKFEX</AccountingEntityID>
            <LocationID>Site~Gouda</LocationID>
            <ActionCriteria>
                <ActionExpression actionCode="Add"/>
            </ActionCriteria>
        </Sync>
        <Shipment>
            <ShipmentHeader>
                <DocumentID>Shipper~S14-01709</DocumentID>
                <UserArea>
                    <Property>
                        <NameValue type="String" name="UDF1">external info</NameValue>
                    </Property>
                    <Property>
                        <NameValue type="xml" name="sourceAA">
                            <ApplicationArea>
                                <Sender>
                                    <LogicalID schemeVersionID="VMSHPENT:7.0.0.156:AC7726D2"
                                        >lid://infor.visual.visual</LogicalID>
                                    <ComponentID>Visual</ComponentID>
                                    <ConfirmationCode>OnError</ConfirmationCode>
                                </Sender>
                                <CreationDateTime>2015-03-04T09:25:12.107Z</CreationDateTime>
                                <BODID schemeAgencyName="Visual" location="Site~Gouda"
                                    >infor-nid:infor:NKFEX:Site~Gouda:Shipper~S14-01709~1:?Shipment&amp;verb=Sync</BODID>
                            </ApplicationArea>
                        </NameValue>
                    </Property>
                </UserArea>
            </ShipmentHeader>
            <ShipmentItem>
                <ItemID>pippo</ItemID>
            </ShipmentItem>
        </Shipment>
    </DataArea>
</SyncShipment>

XML输出

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="SyncShipment">
        <xsl:copy>
            <!--
            If using XSLT 2.0, all three xsl:apply-templates could
            be replaced with: 
            <xsl:apply-templates select="@*,
                DataArea//ApplicationArea,
                node()[not(self::ApplicationArea)]"/>
            -->
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="DataArea//ApplicationArea"/>
            <xsl:apply-templates select="node()[not(self::ApplicationArea)]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Property[NameValue/ApplicationArea]"/>

</xsl:stylesheet>