2012-05-23 17 views
0

我正在获取需要转换为另一种标准类型的XML文件。我的指尖上有XSLT2,我无法控制任何一个文件的格式。第一个有两个使用数字值的序列来匹配它们。第一个序列可以有0..n秒。如何通过XSLT将两个并排XML结构映射到一起?

一个例子是:

输入:

<foo> 
<structure name="items"> 
    <item> 
     <itemCode>1</itemCode> 
     <itemValue>1111</itemValue> 
    </item> 
    <item> 
     <itemCode>2</itemCode> 
     <itemValue>2222</itemValue> 
    </item> 
</structure> 
<structure name="subItems"> 
    <subItem> 
     <itemCode>1</itemCode> 
     <subValue>12</subValue> 
     <subType>MISC</subType> 
    </subItem> 
    <subItem> 
     <itemCode>1</itemCode> 
     <subValue>15</subValue> 
     <subType>MISC2</subType> 
    </subItem> 
    <subItem> 
     <itemCode>2</itemCode> 
     <subValue>40</subValue> 
     <subType>MISC</subType> 
    </subItem> 
</structure> 
</foo> 

而且我想输出是

<bar> 
<items> 
    <item> 
     <code>1</code> 
     <value>1111</value> 
     <subItems> 
      <subItem> 
       <subValue>12</subValue> 
       <subType>MISC</subType> 
      </subItem> 
      <subItem> 
       <subValue>15</subValue> 
       <subType>MISC2</subType> 
      </subItem>    
     </subItems> 
    </item> 
    <item> 
     <code>2</code> 
     <value>2222</value> 
     <subItems> 
      <subItem> 
       <subValue>40</subValue> 
       <subType>MISC</subType> 
      </subItem> 
     </subItems> 
    </item>   
</items> 
</bar> 

我一直不成功映射item.itemCode简单,因为subItem.itemCode看到下一个之前,XSLT处理器似乎退出第一个序列。我无法知道有多少我会在任何一个序列中获得,所以我不能做一张静态地图。

任何想法?

在此先感谢

+0

我不清楚你的意思*第一个序列可能有0..n秒*。请解释。 – Borodin

回答

1

另一种方法来选择合适的子值是使用关键:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="subitems-by-code" match="subItem" use="itemCode"/> 

    <xsl:template match="foo"> 
    <bar> 
     <items> 
     <xsl:apply-templates select="structure[@name='items']"/> 
     </items> 
    </bar> 
    </xsl:template> 

    <xsl:template match="item"> 
    <item> 
     <xsl:copy-of select="*"/> 
     <subItems> 
     <xsl:apply-templates select="key('subitems-by-code', itemCode)"/> 
     </subItems> 
    </item> 
    </xsl:template> 

    <xsl:template match="subItem"> 
    <subItem> 
     <xsl:copy-of select="subValue|subType"/> 
    </subItem> 
    </xsl:template> 
</xsl:stylesheet> 
0

我不是通常高兴发布一个完整的解决方案,但问题看起来有趣,所以我写了这一点。

请再询问一下您是否需要任何阐述。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:template match="/foo"> 
     <bar> 
      <items> 
       <xsl:apply-templates select="structure[@name='items']/item"> 
        <xsl:sort select="itemCode" /> 
       </xsl:apply-templates> 
      </items> 
     </bar> 
    </xsl:template> 

    <xsl:template match="item"> 

      <item> 
       <code> 
        <xsl:value-of select="itemCode" /> 
       </code> 
       <value> 
        <xsl:value-of select="itemValue" /> 
       </value> 
       <subItems> 
        <xsl:apply-templates select="/foo/structure[@name='subItems']/subItem[itemCode=current()/itemCode]" /> 
       </subItems> 
      </item> 

    </xsl:template> 

    <xsl:template match="subItem"> 

     <subItem> 
      <xsl:copy-of select="subValue"/> 
      <xsl:copy-of select="subType"/> 
     </subItem> 

    </xsl:template> 

</xsl:stylesheet> 

输出

<?xml version="1.0" encoding="utf-8"?> 
<bar> 
    <items> 
     <item> 
     <code>1</code> 
     <value>1111</value> 
     <subItems> 
      <subItem> 
       <subValue>12</subValue> 
       <subType>MISC</subType> 
      </subItem> 
      <subItem> 
       <subValue>15</subValue> 
       <subType>MISC2</subType> 
      </subItem> 
     </subItems> 
     </item> 
     <item> 
     <code>2</code> 
     <value>2222</value> 
     <subItems> 
      <subItem> 
       <subValue>40</subValue> 
       <subType>MISC</subType> 
      </subItem> 
     </subItems> 
     </item> 
    </items> 
</bar> 
0

它看起来对我来说,一个简单的分组问题。

<xsl:for-each-group select="items/item, subItems/subItem" group-by="itemCode"> 
    <item> 
    <code><xsl:value-of select="current-group()[self::item]/itemCode"/></code> 
    <value><xsl:value-of select="current-group()/itemValue"/></value> 
    <subItems> 
     <xsl:copy-of select="current-group()[self::subItem]/(subValue, subType)"/> 
    </subItems> 
    </item> 
</xsl:for-each-group>