Как удалить узел, если дочерний узел является дубликатом - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь преобразовать xml, используя xslt1. По сути, я хочу удалить узел, если дочерний узел определенного ребенка уже существует, вход имеет следующий формат:

<Quote>
  … lots of data … 
  <ItemService>
     <ID></ID>
      …
     <Product>
       <InternalId>value</InternalId>
       <DeliveryInfo>
           <lots of subitems>
       </Deliveryinfo>
       <service>SERVICETEYPE</service>
       <some more infos/>
     </Product>
     …
  </Itemservice>
  <ItemService>
     <ID></ID>
      …
     <Product>
       <InternalId>value</InternalId>
       <DeliveryInfo>
           <lots of subitems>
       </deliveryinfo>
       <service>SERVICETEYPE</service>
       <some more infos/>
    </Product>
     … 
  </ItemService>
 … some more data …
</quote>

Так что я хочу удалить, если другой с таким же значением уже существует. скажем, у нас есть 10 ItemServices, где есть три, где значение Product / service равно 'Assembly', я хочу, чтобы в выходных данных оставалось только одно (не важно, какой). Я пробовал так много вещей, но это никогда не складывается ... Я думаю, что это идет в правильном направлении, хотя это и не работа ... Любая помощь очень ценится, xslt не моя чашка чая, и эта действительно меня раздражает ...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:key name="product" match="Product" use="concat(generate-id(parent::*), service)"/> 

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

<xsl:template match="ItemService">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="Product[generate-id(.) = generate-id(key('product' , concat(generate-id(parent::*), service))[1])]" />
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

1 Ответ

0 голосов
/ 23 апреля 2020

Если я угадываю (!) Правильно, вы хотите сделать что-то вроде:

XSLT 1.0

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

<xsl:key name="item-by-service" match="ItemService" use="Product/service" />

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

<xsl:template match="Quote">
    <xsl:copy>
        <xsl:apply-templates select="*[not(self::ItemService)]"/>
        <!-- keep only distinct items -->
        <xsl:apply-templates select="ItemService[generate-id(.) = generate-id(key('item-by-service', Product/service)[1])]" />
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

, которое можно уменьшить до:

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

<xsl:key name="item-by-service" match="ItemService" use="Product/service" />

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

<!-- remove duplicate items -->
<xsl:template match="ItemService[not(generate-id(.) = generate-id(key('item-by-service', Product/service)[1]))]"/>

</xsl:stylesheet>

ВАЖНО:

XML чувствителен к регистру: Service не совпадает с service и </product> не закрывается <Product>.

...