在XSL中组合两个节点集

时间:2011-12-20 23:47:40

标签: xslt

我有以下XML:

<root>
  <row>
    <elem>Timestamp</elem>
    <elem>ERB.CHW.BTU_CV</elem>
    <elem>ERB.CHW.BTU1_CV</elem>
    <elem>ERB.HW.BTU_CV</elem>
    <elem>ERB.HW.BTU1_CV</elem>
    <elem>ERB.KW.DEMAND_CV</elem>
    <elem>ERB.KWH.MT_CV</elem>
    <elem></elem>
  </row>
  <row>
    <elem>2011/09/30 11:21:13.9062</elem>
    <elem>2.307609E+09</elem>
    <elem>1880067</elem>
    <elem>1.068635E+08</elem>
    <elem>1340.386</elem>
    <elem>448.8</elem>
    <elem>1427723</elem>
    <elem></elem>
  </row>
</root>

我想改变它,以便第一个<row>定义新元素(通过<elem>),后面的每个非空<elem>提供值 - 例如:

<root>
  <row>
    <Timestamp>2011/09/30 11:21:13.9062</Timestamp>
    <ERB.CHW.BTU_CV>2.307609E+09</ERB.CHW.BTU_CV>
    <ERB.CHW.BTU1_CV>1880067</ERB.CHW.BTU1_CV>
    <ERB.HW.BTU_CV>1.068635E+08</ERB.HW.BTU_CV>
    <ERB.HW.BTU1_CV>1340.386</ERB.HW.BTU1_CV>
    <ERB.KW.DEMAND_CV>448.8</ERB.KW.DEMAND_CV>
    <ERB.KWH.MT_CV>1427723</ERB.KWH.MT_CV>
  </row>
</root>

有两点需要注意:

  1. 请注意如何从源结构中删除空白<elem>元素。
  2. 这适用于任意数量的<row>节点集。
  3. 我觉得这应该很简单,但我甚至都在努力想知道从哪里开始。帮助

    编辑: RE:上面的#2,我不打算复制初始<row>节点集(用于定义新元素)。相反,该解决方案应适用于包含数据点的任何<row>节点集(即,如果第二个<row>节点集连续重复5次)。

2 个答案:

答案 0 :(得分:2)

以下样式表生成请求的结果:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <!-- ignore even-numbered rows -->
    <xsl:template match="row[position() mod 2 = 0]"/>
    <!-- non-empty elem nodes of odd-numbered rows -->
    <xsl:template match="elem[normalize-space()]">
    <xsl:variable name="pos" select="position()"/>
        <xsl:element name="{text()}">
            <xsl:value-of select="../following-sibling::row[1]/elem[$pos]"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="elem"/>
</xsl:stylesheet>

<强>解释

  • Identity Transform用于通过未更改的
  • 复制大多数节点
  • 最初跳过所有偶数行
  • 当处理每个奇数行的(非空)elem元素时,我们在该行的后续兄弟中的同一位置抓取elem的值

答案 1 :(得分:2)

此转化

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

 <xsl:variable name="vElems" select=
     "/*/row[1]/elem[normalize-space()]"/>


 <xsl:template match="/*">
  <root>
    <xsl:apply-templates select="row[position() >1]"/>
  </root>
 </xsl:template>

 <xsl:template match="row">
  <row>
   <xsl:apply-templates select="$vElems">
    <xsl:with-param name="pValues"
      select="elem"/>
    </xsl:apply-templates>
  </row>
 </xsl:template>

 <xsl:template match="elem">
  <xsl:param name="pValues"/>
  <xsl:variable name="vPos" select="position()"/>

  <xsl:element name="{.}">
   <xsl:value-of select="$pValues[$vPos]"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

应用于以下XML文档(提供的另外一个数据行)

<root>
    <row>
        <elem>Timestamp</elem>
        <elem>ERB.CHW.BTU_CV</elem>
        <elem>ERB.CHW.BTU1_CV</elem>
        <elem>ERB.HW.BTU_CV</elem>
        <elem>ERB.HW.BTU1_CV</elem>
        <elem>ERB.KW.DEMAND_CV</elem>
        <elem>ERB.KWH.MT_CV</elem>
        <elem></elem>
    </row>
    <row>
        <elem>2011/09/30 11:21:13.9062</elem>
        <elem>2.307609E+09</elem>
        <elem>1880067</elem>
        <elem>1.068635E+08</elem>
        <elem>1340.386</elem>
        <elem>448.8</elem>
        <elem>1427723</elem>
        <elem></elem>
    </row>
    <row>
        <elem>2011/09/31 11:22:33.9063</elem>
        <elem>3.418609E+10</elem>
        <elem>1991073</elem>
        <elem>1.068635E+08</elem>
        <elem>1340.386</elem>
        <elem>452.5</elem>
        <elem>169578</elem>
        <elem></elem>
    </row>
</root>

生成想要的正确结果

<root>
   <row>
      <Timestamp>2011/09/30 11:21:13.9062</Timestamp>
      <ERB.CHW.BTU_CV>2.307609E+09</ERB.CHW.BTU_CV>
      <ERB.CHW.BTU1_CV>1880067</ERB.CHW.BTU1_CV>
      <ERB.HW.BTU_CV>1.068635E+08</ERB.HW.BTU_CV>
      <ERB.HW.BTU1_CV>1340.386</ERB.HW.BTU1_CV>
      <ERB.KW.DEMAND_CV>448.8</ERB.KW.DEMAND_CV>
      <ERB.KWH.MT_CV>1427723</ERB.KWH.MT_CV>
   </row>
   <row>
      <Timestamp>2011/09/31 11:22:33.9063</Timestamp>
      <ERB.CHW.BTU_CV>3.418609E+10</ERB.CHW.BTU_CV>
      <ERB.CHW.BTU1_CV>1991073</ERB.CHW.BTU1_CV>
      <ERB.HW.BTU_CV>1.068635E+08</ERB.HW.BTU_CV>
      <ERB.HW.BTU1_CV>1340.386</ERB.HW.BTU1_CV>
      <ERB.KW.DEMAND_CV>452.5</ERB.KW.DEMAND_CV>
      <ERB.KWH.MT_CV>169578</ERB.KWH.MT_CV>
   </row>
</root>