我有一个从库存系统输出的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,所以使用它们的解决方案会很棒。
由于
答案 0 :(得分:1)
我认为这可以通过纯XSLT解决方案来完成。我通过首先为每个产品定义一个密钥(一个 StockSalesRec , Type 的'')来实现它,其中查找为参考最新的前一个供应商记录( 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>
请注意在创建产品节点时使用identity变换,允许将额外的子元素添加到输入XML,而无需更改XSLT。