XSL转换 - 掌握细节

时间:2013-05-05 11:51:06

标签: xml xslt

我需要将XML从一个结构转换为另一个结构。我不知道该怎么做。第一个xml看起来并不像主细节,但结果需要看起来像肥大细节。

   <?xml version = '1.0' encoding = 'UTF-8'?>
    <Root-Element xmlns="http://example.com/ReadProductB">
       <RECORD1>
          <C2>QGGG9.A1-1</C2>
       </RECORD1>
       <RECORD2>
          <C2>xflowcode</C2>
          <C3>FL1</C3>
       </RECORD2>
       <RECORD2>
          <C2>xtilo</C2>
          <C3>1234</C3>
       </RECORD2>
       <RECORD2>
          <C2>xwat</C2>
          <C3>75</C3>
       </RECORD2>
       <RECORD1>
          <C2>QGGG9.A1-2</C2>
       </RECORD1>
       <RECORD2>
          <C2>xflowcode</C2>
          <C3>FL1</C3>
       </RECORD2>
       <RECORD2>
          <C2>xtilo</C2>
          <C3>1234</C3>
       </RECORD2>
       <RECORD2>
          <C2>xwat</C2>
          <C3>75</C3>
       </RECORD2>
    </Root-Element>

这是我想要的结果。

   <?xml version = '1.0' encoding = 'UTF-8'?>
    <ns0:ProductCollection xmlns:ns0="http://example.com/ReadProductBB" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <ns0:RECORD1>
          <ns0:C2>QGGG9.A1-1</ns0:C2>
          <ns0:RECORD2Collection>
             <ns0:RECORD2>
                <ns0:C2>xflowcode</ns0:C2>
                <ns0:C3>FL1</ns0:C3>
             </ns0:RECORD2>
             <ns0:RECORD2>
                <ns0:C2>xtilo</ns0:C2>
                <ns0:C3>1234</ns0:C3>
             </ns0:RECORD2>
             <ns0:RECORD2>
                <ns0:C2>xwat</ns0:C2>
                <ns0:C3>75</ns0:C3>
             </ns0:RECORD2>
          </ns0:RECORD2Collection>
       </ns0:RECORD1>
       <ns0:RECORD1>
          <ns0:C2>QGGG9.A1-2</ns0:C2>
          <ns0:RECORD2Collection>
             <ns0:RECORD2>
                <ns0:C2>xflowcode</ns0:C2>
                <ns0:C3>FL1</ns0:C3>
             </ns0:RECORD2>
             <ns0:RECORD2>
                <ns0:C2>xtilo</ns0:C2>
                <ns0:C3>1234</ns0:C3>
             </ns0:RECORD2>
             <ns0:RECORD2>
                <ns0:C2>xwat</ns0:C2>
                <ns0:C3>75</ns0:C3>
             </ns0:RECORD2>
          </ns0:RECORD2Collection>
       </ns0:RECORD1>
    </ns0:ProductCollection>

请帮忙。感谢

2 个答案:

答案 0 :(得分:1)

此样式表使用通用模板将原始元素移动到名称空间ns0中具有相同名称的元素。

RECORD2元素与其对应的RECORD1元素配对,方法是使用generate-id标识当前RECORD1,然后处理所有后续RECORD2元素第一个前面的RECORD1元素具有相同的ID。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:src="http://example.com/ReadProductB"
    xmlns:ns0="http://example.com/ReadProductBB"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="src"
    version="1.0">

    <xsl:strip-space elements="*"/>
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

    <xsl:template match="/src:Root-Element">
        <ns0:ProductCollection>
            <xsl:apply-templates select="src:RECORD1"/>
        </ns0:ProductCollection>
    </xsl:template>

    <xsl:template match="src:RECORD1">
        <ns0:RECORD1>
            <xsl:apply-templates/>
            <xsl:variable name="record1" select="generate-id()"/>
            <ns0:RECORD2Collection>
                <xsl:for-each select="following-sibling::src:RECORD2">
                    <xsl:if test="generate-id(preceding-sibling::src:RECORD1[1]) = $record1">
                        <xsl:apply-templates select="."/>
                    </xsl:if>
                </xsl:for-each>
            </ns0:RECORD2Collection>
        </ns0:RECORD1>
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="ns0:{local-name(current())}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

<强>输出

<?xml version="1.0" encoding="UTF-8"?>
<ns0:ProductCollection xmlns:ns0="http://example.com/ReadProductBB" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <ns0:RECORD1>
      <ns0:C2>QGGG9.A1-1</ns0:C2>
      <ns0:RECORD2Collection>
         <ns0:RECORD2>
            <ns0:C2>xflowcode</ns0:C2>
            <ns0:C3>FL1</ns0:C3>
         </ns0:RECORD2>
         <ns0:RECORD2>
            <ns0:C2>xtilo</ns0:C2>
            <ns0:C3>1234</ns0:C3>
         </ns0:RECORD2>
         <ns0:RECORD2>
            <ns0:C2>xwat</ns0:C2>
            <ns0:C3>75</ns0:C3>
         </ns0:RECORD2>
      </ns0:RECORD2Collection>
   </ns0:RECORD1>
   <ns0:RECORD1>
      <ns0:C2>QGGG9.A1-2</ns0:C2>
      <ns0:RECORD2Collection>
         <ns0:RECORD2>
            <ns0:C2>xflowcode</ns0:C2>
            <ns0:C3>FL1</ns0:C3>
         </ns0:RECORD2>
         <ns0:RECORD2>
            <ns0:C2>xtilo</ns0:C2>
            <ns0:C3>1234</ns0:C3>
         </ns0:RECORD2>
         <ns0:RECORD2>
            <ns0:C2>xwat</ns0:C2>
            <ns0:C3>75</ns0:C3>
         </ns0:RECORD2>
      </ns0:RECORD2Collection>
   </ns0:RECORD1>
</ns0:ProductCollection>

答案 1 :(得分:0)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:b="http://example.com/ReadProductB"
    xmlns:bb="http://example.com/ReadProductBB"
    version="1.0">
    <xsl:output indent="yes"/>

    <!--
        identity template
        https://en.wikipedia.org/wiki/Identity_transform
    -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!--
        converts elements from the namespace "http://example.com/ReadProductB"
        to "http://example.com/ReadProductBB" 
    -->
    <xsl:template match="b:*">
        <xsl:element name="bb:{local-name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="b:Root-Element">  
        <!--Convert b:Root-Element into bb:ProductCollection-->
        <bb:ProductCollection>
            <!--and then "push" only the b:RECORD1 elements -->
            <xsl:apply-templates select="b:RECORD1"/>
        </bb:ProductCollection>
    </xsl:template>

    <xsl:template match="b:RECORD1">
        <!--Convert the RECORD1 to new namespace -->
        <bb:RECORD1>
            <!-- "push" it's children 
            (which will match the generic templates above)-->
            <xsl:apply-templates select="@*|node()"/>
            <bb:RECORD2Collection>
              <!--and "push" the RECORD2 elements that are 
                between this RECORD1 element and the next(or the end) -->
              <xsl:apply-templates select="following-sibling::b:RECORD2
                      [generate-id(preceding-sibling::b:RECORD1[1])
                       = generate-id(current())]" />
            </bb:RECORD2Collection>
        </bb:RECORD1>
    </xsl:template>

</xsl:stylesheet>