2011-07-20 13 views
1

我有一个股票系统,它不受结构特别好输出的XML文档:如何基于邻近节点同胞重新构造这个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

我认为这可以用纯粹的XSLT解决方案来完成。我首先定义一个关键的每一个产品(一个StockSalesRec以'“一个型)该查询是最近前面的供应商记录的参考(一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。

+0

太棒了!很好解释,非常感谢。 – Jamie