XSLT转换将XML转换为自定义XML以映射到DB中的表模式

时间:2016-05-13 00:17:27

标签: xml xslt xpath

我正在尝试将以下XML1转换为XML2。但无法做到,也无法找到类似的例子。罐头有人帮忙。这是我第一次尝试使用XSLT转换XML。

XML1(当前XML):

<Data>

 <Set label="NY">        
 <value>42.000000000000000</value>
 <value>339.000000000000000</value>
 </Set>

 <Set label="NJ">        
 <value>0.000000000000000</value>
 <value>14.000000000000000</value>
 </Set>

 <Set label="TN">        
 <value>0.000000000000000</value>
 <value>14.000000000000000</value>
 </Set>

</Data>

XML 2(所需的XML):

<Data>

 <Set1 label="NY">
 <datapoint1>42.000000000000000</datapoint1>
 </Set1>

 <Set1 label="NJ">        
 <datapoint1>0.000000000000000</datapoint1>
 </Set1>

 <Set1 label="TN">        
 <datapoint1>0.000000000000000</datapoint1>
 </Set1>

 <Set2 label="NY">
 <datapoint2>339.000000000000000</datapoint2>
 </Set2>

 <Set2 label="NJ">        
 <datapoint2>14.000000000000000</datapoint2>
 </Set2>

 <Set2 label="TN">        
 <datapoint2>14.000000000000000</datapoint2>
 </Set2>

</Data>

2 个答案:

答案 0 :(得分:1)

这是XSLT V1.0。请让我知道这对你有没有用。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <xsl:variable name="var1_initial" select="."/>
        <Data>
            <xsl:for-each select="Data/Set">
                <xsl:variable name="var2_current" select="."/>
                <Set1>
                    <xsl:attribute name="label">
                        <xsl:value-of select="@label"/>
                    </xsl:attribute>
                    <xsl:for-each select="value">
                        <xsl:variable name="var3_current" select="."/>
                        <datapoint1>
                            <xsl:value-of select="number(.)"/>
                        </datapoint1>
                    </xsl:for-each>
                </Set1>
            </xsl:for-each>
            <xsl:for-each select="Data/Set">
                <xsl:variable name="var4_current" select="."/>
                <Set2>
                    <xsl:attribute name="label">
                        <xsl:value-of select="@label"/>
                    </xsl:attribute>
                    <xsl:for-each select="value">
                        <xsl:variable name="var5_current" select="."/>
                        <datapoint2>
                            <xsl:value-of select="number(.)"/>
                        </datapoint2>
                    </xsl:for-each>
                </Set2>
            </xsl:for-each>
        </Data>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

这是另一个XSLT 1.0选项...

XML输入

<Data>

    <Set label="NY">        
        <value>42.000000000000000</value>
        <value>339.000000000000000</value>
    </Set>

    <Set label="NJ">        
        <value>0.000000000000000</value>
        <value>14.000000000000000</value>
    </Set>

    <Set label="TN">        
        <value>0.000000000000000</value>
        <value>14.000000000000000</value>
    </Set>

</Data>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates select="@*|Set/value[1]"/>
      <xsl:apply-templates select="Set/value[2]"/>
    </xsl:copy>    
  </xsl:template>

  <xsl:template match="value">
    <xsl:variable name="pos">
      <xsl:number/>
    </xsl:variable>
    <xsl:element name="Set{$pos}">
      <xsl:copy-of select="../@label"/>
      <datapoint><xsl:value-of select="."/></datapoint>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

XML输出

<Data>
   <Set1 label="NY">
      <datapoint>42.000000000000000</datapoint>
   </Set1>
   <Set1 label="NJ">
      <datapoint>0.000000000000000</datapoint>
   </Set1>
   <Set1 label="TN">
      <datapoint>0.000000000000000</datapoint>
   </Set1>
   <Set2 label="NY">
      <datapoint>339.000000000000000</datapoint>
   </Set2>
   <Set2 label="NJ">
      <datapoint>14.000000000000000</datapoint>
   </Set2>
   <Set2 label="TN">
      <datapoint>14.000000000000000</datapoint>
   </Set2>
</Data>

如果value元素的数量未知或可能会有所不同,那么还有一个选项......

XML输入(已修改为具有不同数量的value元素)

<Data>

    <Set label="NY">        
        <value>42.000000000000000</value>
        <value>339.000000000000000</value>
    </Set>

    <Set label="NJ">        
        <value>0.000000000000000</value>
        <value>14.000000000000000</value>
        <value>77.000000000000000</value>
    </Set>

    <Set label="TN">        
        <value>0.000000000000000</value>
        <value>14.000000000000000</value>
        <value>77.000000000000000</value>
        <value>18.000000000000000</value>
    </Set>

</Data>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!--Create a key of sets based on the number of values.-->
  <xsl:key name="sets" match="Set" use="count(value)"/>

  <!--Determine the max number of values in a set. (Using key above.)-->
  <xsl:variable name="maxValues">
    <xsl:for-each select="/Data/Set[count(.|key('sets',count(value))[1])=1]">
      <xsl:sort select="count(value)" order="descending"/>
      <xsl:if test="position()=1">
        <xsl:value-of select="count(value)+1"/>
      </xsl:if>
    </xsl:for-each>    
  </xsl:variable>

  <!--Identity transform. Copies attributes and nodes unchanged.-->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/Data">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:call-template name="processSets">
        <xsl:with-param name="currentIteration" select="1"/>
      </xsl:call-template>
    </xsl:copy>
  </xsl:template>

  <xsl:template name="processSets">
    <xsl:param name="currentIteration"/>
    <xsl:apply-templates select="Set/value[position()=$currentIteration]"/>
    <xsl:if test="$maxValues > $currentIteration + 1">
      <xsl:call-template name="processSets">
        <xsl:with-param name="currentIteration" select="$currentIteration + 1"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

  <xsl:template match="value">
    <xsl:variable name="pos">
      <xsl:number/>
    </xsl:variable>
    <xsl:element name="Set{$pos}">
      <xsl:apply-templates select="../@label"/>
      <datapoint><xsl:value-of select="."/></datapoint>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

XML输出

<Data>
   <Set1 label="NY">
      <datapoint>42.000000000000000</datapoint>
   </Set1>
   <Set1 label="NJ">
      <datapoint>0.000000000000000</datapoint>
   </Set1>
   <Set1 label="TN">
      <datapoint>0.000000000000000</datapoint>
   </Set1>
   <Set2 label="NY">
      <datapoint>339.000000000000000</datapoint>
   </Set2>
   <Set2 label="NJ">
      <datapoint>14.000000000000000</datapoint>
   </Set2>
   <Set2 label="TN">
      <datapoint>14.000000000000000</datapoint>
   </Set2>
   <Set3 label="NJ">
      <datapoint>77.000000000000000</datapoint>
   </Set3>
   <Set3 label="TN">
      <datapoint>77.000000000000000</datapoint>
   </Set3>
   <Set4 label="TN">
      <datapoint>18.000000000000000</datapoint>
   </Set4>
</Data>