0

我得到一个需要转换成另一种标准类型的 XML 文件。XSLT2 触手可及,但我无法控制任一文件的格式。第一个有两个序列,它们使用一个数值来匹配它们。第一个序列可能有 0..n 的第二个。

一个例子是:

输入:

<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 处理器似乎在看到下一个序列之前退出了第一个序列。我无法知道我将在任一序列中获得多少,所以我无法制作静态地图。

有任何想法吗?

提前致谢

4

3 回答 3

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>
于 2012-05-23T18:03:15.153 回答
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>
于 2012-05-23T17:53:41.287 回答
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>
于 2012-05-23T20:02:51.367 回答