Как преобразовать ввод XML с несколькими одинаковыми элементами в вывод XML без идентичных элементов - PullRequest
0 голосов
/ 20 марта 2012

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

<?xml version="1.0"?>
<InputShipmentSchedule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<DataArea>
    <ShipmentSchedule>
        <ShipmentScheduleLine>
            <ManufacturingItem>
                <ItemID>
                    <ID>P313503</ID>
                </ItemID>
            </ManufacturingItem>                
        </ShipmentScheduleLine>
        <ShipmentScheduleLine>
            <ManufacturingItem>
                <ItemID>
                    <ID>P313503</ID>
                </ItemID>
            </ManufacturingItem>            
        </ShipmentScheduleLine>
        <ShipmentScheduleLine>
            <ManufacturingItem>
                <ItemID>
                    <ID>P313504</ID>
                </ItemID>
            </ManufacturingItem>            
        </ShipmentScheduleLine>
        <ShipmentScheduleLine>
            <ManufacturingItem>
                <ItemID>
                    <ID>P313504</ID>
                </ItemID>
            </ManufacturingItem>            
        </ShipmentScheduleLine>
    </ShipmentSchedule>
</DataArea>
</InputShipmentSchedule>

Я сделал следующий файл преобразователя xsl:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>
<xsl:preserve-space elements="*"/>
<xsl:template match="InputShipmentSchedule">
    <xsl:call-template name="CreateShipmentScheduleXmlns"/>
</xsl:template>

<xsl:template name="CreateShipmentScheduleXmlns">
    <xsl:element name="Output_Data">
        <xsl:element name="ShipmentSchedule">
                <xsl:call-template name="part_detail_template">
                    <xsl:with-param name="currentPartLine" select="DataArea/ShipmentSchedule/ShipmentScheduleLine"/>
                    <xsl:with-param name="nextPartLine" select="DataArea/ShipmentSchedule/ShipmentScheduleLine/following-sibling::ShipmentScheduleLine"/>
                </xsl:call-template>                
        </xsl:element>  <!-- ShipmentSchedule tag end -->
    </xsl:element>  <!-- Output_Data tag end -->
</xsl:template> <!-- CreateShipmentScheduleXmlns template end -->

<xsl:template name="part_detail_template">
    <xsl:param name="currentPartLine"/>
    <xsl:param name="nextPartLine"/>
    <xsl:element name="Part_Detail">  <!-- Part_Detail tag start -->
        <xsl:variable name="part_no" select="$currentPartLine/ManufacturingItem/ItemID/ID"/>
        <xsl:element name="part_no">
            <xsl:attribute name="value">
                <xsl:value-of select="$part_no"/>
            </xsl:attribute>
        </xsl:element>
    </xsl:element>  <!-- Part_Detail tag end -->
    <xsl:variable name="currentItem" select="$currentPartLine/ManufacturingItem/ItemID/ID"/>
    <xsl:variable name="nextItem" select="$nextPartLine/ManufacturingItem/ItemID/ID"/>
    <xsl:choose>            
        <xsl:when test="$nextPartLine and $nextItem != $currentItem">
            <xsl:call-template name="part_detail_template">
                <xsl:with-param name="currentPartLine" select="$nextPartLine"/>
                <xsl:with-param name="nextPartLine" select="$nextPartLine/following-sibling::ShipmentScheduleLine"/>
            </xsl:call-template>
        </xsl:when>
    </xsl:choose>
</xsl:template>  <!-- part_detail_template tag end -->                                        
</xsl:stylesheet>

Но выходной файл xml по-прежнему содержит избыточный P313503 следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<Output_Data>
<ShipmentSchedule>
<Part_Detail>
<part_no value="P313503"/>
</Part_Detail>
<Part_Detail>
<part_no value="P313503"/>
</Part_Detail>
<Part_Detail>
<part_no value="P313504"/>
</Part_Detail>
</ShipmentSchedule>
</Output_Data>

Я не знаю, почему элемент "part_no" ("P313503") появился бы дважды.Предполагается, что в выходном xml-файле содержится не избыточный элемент "part_no".Что я сделал не так в приведенном выше файле xsl?Любой комментарий или предложение будет принята с благодарностью.Заранее спасибо.

1 Ответ

1 голос
/ 20 марта 2012
                <xsl:with-param name="currentPartLine" 
                select="DataArea/ShipmentSchedule/ShipmentScheduleLine"/>
                <xsl:with-param name="nextPartLine" 
                select="DataArea/ShipmentSchedule/ShipmentScheduleLine/
                                   following-sibling::ShipmentScheduleLine"/>

Эти два выражения выбирают один и тот же набор узлов.DataArea/ShipmentSchedule/ShipmentScheduleLine выбирает все элементы ShipmentScheduleLine, а не только первый, и поэтому добавление following-sibling::ShipmentScheduleLine не выбирает никаких других узлов.

В XSLT2 проблемы с группировкой намного проще, чем в XSLT1но при условии, что вы застряли на 1 по какой-то причине.Google для "muenchian группировки", которая приведет вас к этому решению:

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

<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>

<xsl:key name="n" match="ItemID" use="ID"/>

<xsl:template match="/">
 <Output_Data>
  <ShipmentSchedule>
   <xsl:for-each select="//ManufacturingItem/ItemID[generate-id()=
             generate-id(key('n',.))]">
    <Part_Detail>
     <part_no value="{.}"/>
    </Part_Detail>
   </xsl:for-each>
  </ShipmentSchedule>
 </Output_Data>
</xsl:template>

</xsl:stylesheet>

, который производит:

$ saxon man.xml man.xsl
<?xml version="1.0" encoding="utf-8"?>
<Output_Data>
   <ShipmentSchedule>
      <Part_Detail>
         <part_no value="P313503"/>
      </Part_Detail>
      <Part_Detail>
         <part_no value="P313504"/>
      </Part_Detail>
   </ShipmentSchedule>
</Output_Data>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...