Как мне реструктурировать этот XML-документ на основе братьев и сестер близких узлов? - PullRequest
1 голос
/ 20 июля 2011

У меня есть документ XML, выведенный из стандартной системы, который не очень хорошо структурирован:

<root>
    <StockSalesRec Type="SH">                               
        <Reference>A Supplier</Reference>     
        <StockNum></StockNum>                      
        <Description></Description>
        ...
    </StockSalesRec>                                        
    <StockSalesRec Type="  ">                               
        <Reference>12345</Reference>     
        <StockNum>00001</StockNum>                      
        <Description>Item description</Description>
        ...
    </StockSalesRec>                                        
    <StockSalesRec Type="  ">                               
        <Reference>67890</Reference>     
        <StockNum>00002</StockNum>                      
        <Description>Another description</Description>
        ...
    </StockSalesRec>
    ...
</root>

Каждый <StockSalesRec Type=SH> является поставщиком, и все до следующего <StockSalesRec Type=SH> является продуктом этого поставщика. Перед использованием этого документа я хотел бы реструктурировать его так, чтобы он выглядел примерно так:

<root>
    <supplier name="A Supplier">
        <product>
            <Reference>67890</Reference>     
            <StockNum>00002</StockNum>     
            <Description>Another description</Description>
        </product>
        ....
    </supplier>
    ....
</root>

Как бы я изменил документ таким образом? Я попытался использовать XSL для решения, однако застрял довольно быстро. В настоящее время я изучаю Ruby в последнее время, поэтому было бы неплохо использовать его.

Спасибо

1 Ответ

1 голос
/ 20 июля 2011

Я думаю, что это можно сделать с помощью чистого решения XSLT.Я достиг этого, сначала определив ключ для каждого продукта ( StockSalesRec с Type of ''), для которого поиск является Reference Самая последняя предыдущая запись поставщика (a StockSalesRec с Типом из 'SH')

<xsl:key 
  name="Stock" 
  match="StockSalesRec[@Type='  ']" 
  use="(preceding-sibling::StockSalesRec[@Type='SH'])[last()]/Reference" />

Затем вы можете сопоставить на каждом узле поставщика, например,

<xsl:apply-templates select="StockSalesRec[@Type='SH']" />

И затем для каждого такого узла поставщика вы можете прочитать все записи Продукта, используя ранее определенный ключ

<xsl:apply-templates select="key('Stock', Reference)" />

Если все это указать, то вы получите ....

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

   <xsl:key 
      name="Stock" 
      match="StockSalesRec[@Type='  ']" 
      use="(preceding-sibling::StockSalesRec[@Type='SH'])[last()]/Reference"/>

   <xsl:template match="/root">
      <xsl:copy>
         <xsl:apply-templates select="StockSalesRec[@Type='SH']"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="StockSalesRec[@Type='SH']">
      <supplier name="{Reference}">
         <xsl:apply-templates select="key('Stock', Reference)"/>
      </supplier>
   </xsl:template>

   <xsl:template match="StockSalesRec[@Type='  ']">
      <product>
         <xsl:apply-templates/>
      </product>
   </xsl:template>

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

</xsl:stylesheet>

Когда вы применяете это к вашему образцу XML, вывод будет следующим:

<root>
   <supplier name="A Supplier">
      <product>
         <Reference>12345</Reference>
         <StockNum>00001</StockNum>
         <Description>Item description</Description>
      </product>
      <product>
         <Reference>67890</Reference>
         <StockNum>00002</StockNum>
         <Description>Another description</Description>
      </product>
   </supplier>
</root>

Обратите внимание на использование преобразования идентификаторов при создании узла продукта, позволяя добавлять дополнительные дочерние элементы во входные данные.XML без необходимости менять XSLT.

...