使用XSLT删除重复节点

时间:2018-04-03 05:03:31

标签: xslt

我正在尝试从以下源XML中删除重复项。

要求1 内部<ns0:Message1>, <UpdateMultipleObjectsOperationsSchema>只会来一次,但<sObject>会重复。我需要删除<AccountId><ContactId>组合已经出现一次的情况。在此示例中,需要删除<sObject>的第3和第4次。

要求2 内部<ns0:Message2>, <UpdateMultipleObjectsOperationsSchema/>可能会重复100次。 <UpdateMultipleObjectsOperationsSchema/>下不需要任何值或子标记。我想删除所有重复项,并且只保留第一个重复项。

XML代码

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
   <ns0:Message1>
      <UpdateMultipleObjectsOperationsSchema>
         <AccountContactRole>
            <Operation>Create</Operation>
            <ObjectType>ACRObject</ObjectType>
            <TransactionLevel>REQUIRED</TransactionLevel>
            <sObjects>
               <sObject>
                  <AccountId>A12345</AccountId>
                  <ContactId>C001</ContactId>
                  <Role>SalesPerson</Role>
               </sObject>
               <sObject>
                  <AccountId>A12345</AccountId>
                  <ContactId>C002</ContactId>
                  <Role>SalesPerson</Role>
               </sObject>
               <sObject>
                  <AccountId>A12345</AccountId>
                  <ContactId>C002</ContactId>
                  <Role>SalesPerson</Role>
               </sObject>
               <sObject>
                  <AccountId>A12345</AccountId>
                  <ContactId>C002</ContactId>
                  <Role>SalesPerson</Role>
               </sObject>
            </sObjects>
         </AccountContactRole>
      </UpdateMultipleObjectsOperationsSchema>
   </ns0:Message1>
   <ns0:Message2>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
      <UpdateMultipleObjectsOperationsSchema/>
   </ns0:Message2>
</ns0:Messages>

预期输出

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
   <ns0:Message1>
      <UpdateMultipleObjectsOperationsSchema>
         <AccountContactRole>
            <Operation>Create</Operation>
            <ObjectType>ACRObject</ObjectType>
            <TransactionLevel>REQUIRED</TransactionLevel>
            <sObjects>
               <sObject>
                  <AccountId>A12345</AccountId>
                  <ContactId>C001</ContactId>
                  <Role>SalesPerson</Role>
               </sObject>
               <sObject>
                  <AccountId>A12345</AccountId>
                  <ContactId>C002</ContactId>
                  <Role>SalesPerson</Role>
               </sObject>
            </sObjects>
         </AccountContactRole>
      </UpdateMultipleObjectsOperationsSchema>
   </ns0:Message1>
   <ns0:Message2>
      <UpdateMultipleObjectsOperationsSchema/>
   </ns0:Message2>
</ns0:Messages>

我是XSL的新手,有点卡住了。真的很感激任何帮助。

这是我尝试的......第一个要求(在此处提到一些帖子后)

请原谅我在XSL中缺乏知识:(

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xhtml="http://www.w3.org/1999/xhtml"
  xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="trip-tth" match="/ns0:Messages/ns0:Message1/UpdateMultipleObjectsOperationsSchema/AccountContactRole/sObjects/sObject" use="concat(AccountId, '+', ContactId)"/>

<xsl:template match="/ns0:Messages/ns0:Message1/UpdateMultipleObjectsOperationsSchema/AccountContactRole/sObjects/">   
    <xsl:copy>
        <xsl:apply-templates select="sObject[generate-id(.) = generate-id( key ('trip-tth', concat(AccountId, '+', ContactId) ) )]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="sObjects">
    <xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>

谢谢!

1 个答案:

答案 0 :(得分:0)

你走在正确的轨道上。您可以通过仅指定match中的元素名称而不是整个XPath来优化键声明。

<xsl:key name="group-key" match="sObject" use="concat(AccountId, '|', ContactId)" />

我们使用identity template将输入XML中的节点和属性按原样复制到输出,然后根据要求重新开始覆盖模板。

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

使用声明的密钥匹配<sObject>

<xsl:template match="sObject[generate-id() = generate-id(key('group-key', concat(AccountId, '|', ContactId))[1])]">
    <xsl:copy>
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>

通过“不执行任何操作”模板删除剩余的<sObject>元素。

<xsl:template match="sObject" />

对于第二个要求,您可以保留第一个<UpdateMultipleObjectsOperationsSchema/>并使用以下模板删除其余部分。

<xsl:template match="ns0:Message2">
    <xsl:copy>
        <xsl:copy-of select="UpdateMultipleObjectsOperationsSchema[1]" />
    </xsl:copy>
</xsl:template>
<xsl:template match="ns0:Message2/UpdateMultipleObjectsOperationsSchema" />

整个XSLT如下

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*" />

    <xsl:key name="group-key" match="sObject" use="concat(AccountId, '|', ContactId)" />

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

    <xsl:template match="sObject[generate-id() = generate-id(key('group-key', concat(AccountId, '|', ContactId))[1])]">
        <xsl:copy>
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="sObject" />

    <xsl:template match="ns0:Message2">
        <xsl:copy>
            <xsl:copy-of select="UpdateMultipleObjectsOperationsSchema[1]" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="ns0:Message2/UpdateMultipleObjectsOperationsSchema" />
</xsl:stylesheet>

输出

<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
    <ns0:Message1>
        <UpdateMultipleObjectsOperationsSchema>
            <AccountContactRole>
                <Operation>Create</Operation>
                <ObjectType>ACRObject</ObjectType>
                <TransactionLevel>REQUIRED</TransactionLevel>
                <sObjects>
                    <sObject>
                        <AccountId>A12345</AccountId>
                        <ContactId>C001</ContactId>
                        <Role>SalesPerson</Role>
                    </sObject>
                    <sObject>
                        <AccountId>A12345</AccountId>
                        <ContactId>C002</ContactId>
                        <Role>SalesPerson</Role>
                    </sObject>
                </sObjects>
            </AccountContactRole>
        </UpdateMultipleObjectsOperationsSchema>
    </ns0:Message1>
    <ns0:Message2>
        <UpdateMultipleObjectsOperationsSchema />
    </ns0:Message2>
</ns0:Messages>