【问题标题】:Grouping siblings ending with a matched element对以匹配元素结尾的兄弟姐妹进行分组
【发布时间】:2010-11-11 17:41:09
【问题描述】:

我有一个非常大的 XSL 文件来将 XML 转换为 CSV。基本上,XML 的结构是表数据。此表中大约有 90 列(不是我的决定!)。这些列组成一个列组。

每个列组都有一个第一和第二个值,一个可选的第三个值和一个选择,它决定在组中选择哪个值 - 这由 F、S 或 T 表示 - (F)irst/(S)econd /(第三。 该行的主键是日期时间列。

XML 如下(不是缩减版)。因此,我们必须以第 30 列为例。

<data>
 <columns>
  <column id="0">
   <name>Date Time</name>
   <type>DateTime</type>
  </column>
  <column id="1">
   <name>Column Group 1 First</name>
   <type>Double</type>
  </column>
  <column id="2">
   <name>Column Group 1 Second</name>
   <type>Double</type>
  </column>
  <column id="3">
   <name>Column Group 1 Third</name>
   <type>Double</type>
  </column>
  <column id="4">
   <name>Column Group 1 Selection</name>
   <type>String</type>
  </column>
  <column id="5">
   <name>Column Group 2 First</name>
   <type>Double</type>
  </column>
  <column id="6">
   <name>Column Group 2 Second</name>
   <type>Double</type>
  </column>
  <column id="7">
   <name>Column Group 2 Third</name>
   <type>Double</type>
  </column>
  <column id="8">
   <name>Column Group 2 Selection</name>
   <type>String</type>
  </column>
  <!-- This group does not have Third-->
  <column id="9">
   <name>Column Group 3 First</name>
   <type>Double</type>
  </column>
  <column id="10">
   <name>Column Group 3 Second</name>
   <type>Double</type>
  </column>
  <column id="11">
   <name>Column Group 3 Selection</name>
   <type>String</type>
  </column>
 </columns>
 <rows>
  <row id="0">
   <columns>
    <column id="0">
     <name>Date Time</name>
     <universalDate>2010-10-10 11:30:00</universalDate>
    </column>
    <!-- Group 1 - - - - - - - - - - - - - - - - -->
    <column id="1">
     <name>Column Group 1 First</name>
     <displayValue>100.123</displayValue>
     <value>100.123</value>
    </column>
    <column id="2">
     <name>Column Group 1 Second</name>
     <displayValue>Missing</displayValue>
     <value>-2.50E+08</value>
    </column>
    <column id="3">
     <name>Column Group 1 Third</name>
     <displayValue>Missing</displayValue>
     <value>-2.50E+08</value>
    </column>
    <column id="4">
     <name>Column Group 1 Selection</name>
     <displayValue>F</displayValue>
     <value>F</value>
    </column>
    <!-- Group 2 - - - - - - - - - - - - - - - - -->
    <column id="5">
     <name>Column Group 2 First</name>
     <displayValue>Missing</displayValue>
     <value>-2.50E+08</value>
    </column>
    <column id="6">
     <name>Column Group 2 Second</name>
     <displayValue>Missing</displayValue>
     <value>-2.50E+08</value>
    </column>
    <column id="7">
     <name>Column Group 2 Third</name>
     <displayValue>93.123</displayValue>
     <value>93.123</value>
    </column>
    <column id="8">
     <name>Column Group 2 Selection</name>
     <displayValue>T</displayValue>
     <value>T</value>
    </column>
    <!-- Group 3 - - - - - - - - - - - - - - - - -->
    <column id="9">
     <name>Column Group 3 First</name>
     <displayValue>500.3</displayValue>
     <value>500.3</value>
    </column>
    <column id="10">
     <name>Column Group 3 Second</name>
     <displayValue>22.21</displayValue>
     <value>22.21</value>
    </column>
    <column id="11">
     <name>Column Group 3 Third</name>
     <displayValue>S</displayValue>
     <value>S</value>
    </column>
   </columns>
  </row>
  <!-- Other rows omitted -->
 </rows>
</data>

期望的输出是:

Date Time,Column Group 1 Primary,Column Group 1 Secondary,Column Group 1 Third,Column Group 1 Selection
Date Time,Column Group 2 Primary,Column Group 2 Secondary,Column Group 2 Third,Column Group 2 Selection
Date Time,Column Group 3 Primary,Column Group 3 Secondary,Column Group 3 Third,Column Group 3 Selection
... and so on ...

所以输出实际上是:

2010-10-10 11:30:00,100.123,,,F            
2010-10-10 11:30:00,,,93.123,T             
2010-10-10 11:30:00,500.3,22.21,,S         

有几个规则: 如果 displayValue = missing 则输出空字符串。 如果该组没有第三个值,则输出空字符串。

我的 XSL 的第一个实例是对每组看起来很可怕且太大的列重复此检查。

问题是 - 是否可以使用模板输出以下 XML?我才刚刚开始使用模板(感谢其他人在我其他帖子中的帮助),但这让我有点卡住了。

我可以在列和行之间链接以输出表 xml 中的所有行列数据,但这或多或少是根据名称的第一部分将 3 列分组在一起。

此实例的 XSL 如下所示:

<xsl:for-each select="//rows/row">
<xsl:value-of select="columns/column[name='Date Time']/universalDate"/>
<xsl:text>,</xsl:text>
<xsl:if test="number(columns/column[name='Column 1 First']/value)">
    <xsl:value-of select="format-number(columns/column[name='Column 1 First']/value,'0')"/>
  </xsl:if>
  <xsl:text>,</xsl:text>
  <xsl:if test="number(columns/column[name='Column 1 Second']/value)">
    <xsl:value-of select="format-number(columns/column[name='Column 1 Second']/value,'0')"/>
  </xsl:if>
  <xsl:text>,</xsl:text>
  <xsl:if test="number(columns/column[name='Column 1 Third']/value)">
    <xsl:value-of select="format-number(columns/column[name='Column 1 Third']/rawValue,'0')"/>
  </xsl:if>
  <xsl:text>,</xsl:text>
  <xsl:if test="columns/column[name='Column 1 Selection']/value='F'">
    <xsl:value-of select="format-number(columns/column[name='Column 1 First']/value,'0')"/>
  </xsl:if>
  <xsl:if test="columns/column[name='Column 1 Selection']/value='S'">
    <xsl:value-of select="format-number(columns/column[name='Column 1 Second']/value,'0')"/>
  </xsl:if>
  <xsl:if test="columns/column[name='Column 1 Selection']/value='T'">
    <xsl:value-of select="format-number(columns/column[name='Column 1 Third']/value,'0')"/>
  </xsl:if>
  <!-- new line required -->
  <xsl:text>&#xA;</xsl:text>
  <xsl:value-of select="columns/column[name='Date Time']/universalDate"/>
  <xsl:text>,</xsl:text>
  <xsl:if test="number(columns/column[name='Column 2 First']/value)">
    <xsl:value-of select="format-number(columns/column[name='Column 1 First']/value,'0')"/>
  </xsl:if>
  <xsl:text>,</xsl:text>
  <xsl:if test="number(columns/column[name='Column 2 Second']/value)">
    <xsl:value-of select="format-number(columns/column[name='Column 1 Second']/value,'0')"/>
  </xsl:if>
  <xsl:text>,</xsl:text>
  <xsl:if test="number(columns/column[name='Column 2 Third']/value)">
    <xsl:value-of select="format-number(columns/column[name='Column 2 Third']/value,'0')"/>
  </xsl:if>
  <xsl:text>,</xsl:text>
  <xsl:if test="columns/column[name='Column 2 Selection']/value='F'">
    <xsl:value-of select="format-number(columns/column[name='Column 2 First']/value,'0')"/>
  </xsl:if>
  <xsl:if test="columns/column[name='Column 2 Selection']/value='S'">
    <xsl:value-of select="format-number(columns/column[name='Column 2 Second']/value,'0')"/>
  </xsl:if>
  <xsl:if test="columns/column[name='Column 2 Selection']/value='T'">
    <xsl:value-of select="format-number(columns/column[name='Column 2 Third']/value,'0')"/>
  </xsl:if>
  <!-- new line required -->
  <xsl:text>&#xA;</xsl:text>

  <!-- and so on.......  -->

很抱歉在第一次澄清。

谢谢,

安德斯

【问题讨论】:

  • 为您提供的 XML 输入显示一些示例 CSV 输出(使用 EDIT 按钮将其添加到您的问题中)
  • 一点都不清楚。从提供的 XML 文档产生的确切输出应该是什么?请提供确切的输出。另外,应该执行什么处理:请列出从源 XML 节点到所需输出的所有规则和映射。
  • 我已经更新了。希望这次更有意义。

标签: xml xslt transform


【解决方案1】:

这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="row/columns/column[substring(name,16)='First']">
        <xsl:variable name="vOptional"
                      select="following::column[2]
                                 [substring(name,16)='Third']"/>
        <xsl:value-of select="concat(../column[1]/universalDate,',',
                                     displayValue[.!='Missing'],',',
                                     following::column[1]
                                        /displayValue[.!='Missing'],',',
                                     $vOptional/displayValue[.!='Missing'],',',
                                     following::column[2 + boolean($vOptional)]
                                        /displayValue[.!='Missing'],'&#xA;')"/>
    </xsl:template>
    <xsl:template match="data/columns|column"/>
</xsl:stylesheet>

输出:

2010-10-10 11:30:00,100.123,,,F
2010-10-10 11:30:00,,,93.123,T
2010-10-10 11:30:00,500.3,22.21,,S

编辑:更好。我被之前的逻辑卡住了,抱歉。

【讨论】:

  • 嗨亚历杭德罗。我已经转发了这个问题。只是想让我的头脑仍然在 xsl 上。感谢您的回复。对重新发布的问题也会这样做吗?
  • @Andez:这个问题需要澄清。这就是其他人投票反对或投票结束的方式。我看到了你的转贴。不。只需编辑这个。
  • @Alejandro 这次你觉得有意义吗?我试图从我想要表达的内容中阐述出来。我只想从 xsl 的角度稍微解释一下如何处理这个问题 - 有一些指针和 xsl 函数可供查看。
  • @Alejandro - 谢谢。但是我的 xml 略有变化,所以第一列现在是可选的。看来我需要将 First、Second 和 Third 设为未来可选。是否可以遍历节点以找到 Selection 而不是 First 然后查看前面的列并检查 First、Second 或 Third?
  • @Andez:是的,这是可能的。我会举个例子回来。
猜你喜欢
  • 2019-03-27
  • 1970-01-01
  • 1970-01-01
  • 2019-05-06
  • 1970-01-01
  • 1970-01-01
  • 2015-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多