对以匹配元素结尾的兄弟姐妹进行分组

发布于 2024-10-02 16:38:10 字数 8321 浏览 2 评论 0原文

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

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

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 = 缺失则输出空字符串。 如果该组没有第三个值,则输出空字符串。

我的 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.......  -->

很抱歉在第一个实例中进行澄清。

谢谢,

安德斯

I have an extremely large XSL file to transform XML into CSV. Bascially, the structure of the XML is table data. There are about 90 columns in this table (not my decision!). These columns make up a column group.

Each column group has a First and Second value, an optional Third value and a Selection which decides which value was selected in the group - this is indicated by F, S, or T - (F)irst/(S)econd/(T)hird.
The main key on the row is the Date Time column.

The XML is as follows (not this is a cut down version). So we would have up to say Column 30 for example.

<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>

The desired output would be:

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 ...

So the output would actually be:

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         

There are a couple of rules:
if the displayValue = missing then output empty string.
if the group does not have a third value then output empty string.

The first instance of my XSL is to have this check repeated for each set of columns which looks horrendous and is far too large.

The question is - is it possible to output the following XML using Templates? I have only just started working on templates (thanks to help of others in my other postings) but this has got me a little stuck.

I can link between the columns and rows to output all row column data in the table xml but this is more or less grouping 3 columns together based on the first part of the name.

My XSL for this instance looks like:

<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>
</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>
</xsl:text>

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

Sorry for clarifying in the first instances.

Thanks,

Andez

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白况 2024-10-09 16:38:10

此样式表:

<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'],'
')"/>
    </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

编辑:更好。我被锁定在以前的逻辑中,抱歉。

This stylesheet:

<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'],'
')"/>
    </xsl:template>
    <xsl:template match="data/columns|column"/>
</xsl:stylesheet>

Output:

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

Edit: Better. I was lock in previous logic, sorry.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文