2012-03-19 50 views
0

我試圖將包含多個相同元素的xml輸入文件轉換爲將所有相同元素合併爲一個的新xml文件。輸入文件就像是如何將具有多個相同元素的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
   <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。谷歌爲 「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> 
+0

謝謝您的回答。但是,如何使第一個表達式僅選擇第一個節點,而不是所有ShipmentScheduleLine?我試過「DataArea/ShipmentSchedule/ShipmentScheduleLine /」。它沒有刪除輸出xml文件中多餘的「part_no」元素(「P313503」)。 – Charles 2012-03-20 02:12:21

+0

DataArea/ShipmentSchedule/ShipmentScheduleLine [1]將選擇第一個 – 2012-03-20 04:07:58

+0

,如註釋中所述,添加數字謂詞可能會使其工作,但反覆搜索完整路徑效率不高,並且最好使用不同的分組方式,請參閱更新的答案 – 2012-03-20 10:18:35

相關問題