表数据的XSL转换

时间:2010-11-10 14:38:13

标签: xml xslt transform

我有一些XML,它以下列形式存储表中的列信息和行数据:

<?xml version="1.0" encoding="utf-8"?>
<table>
  <columns>
    <column id="1">
      <name>Date</name>
      <type>Date</type>
    </column>
    <column id="2">
      <name>Name</name>
      <type>String</type>
    </column>
  </columns>
  <rows>
    <row id="1">
      <columns>
        <column id="1">
          <name>Date</name>
          <value>1-Dec-2010</value>
          <localDate>1-Dec-2010 00:00:00 GMT</localDate>
        </column>
        <column id="2">
          <name>Name</name>
          <value>Jim</value>
        </column>
      </columns>
    </row>
    <row id="2">
      <columns>
        <column id="1">
          <name>Date</name>
          <value>2-Dec-2010</value>
          <localDate>2-Dec-2010 00:00:00 GMT</localDate>
        </column>
        <column id="2">
          <name>Name</name>
          <value>Jane</value>
        </column>
      </columns>
    </row>
  </rows>
</table>

注意:这是我的xml的缩减版本。我有更多行,并在每列上存储更多信息。

是否可以应用XSL转换,该转换将迭代xml中的每一行并输出每个列值。如果列的类型为DateTime(在列信息中指定),我想输出 localDate 文本值,否则我将只输出文本值。

我可以做一点XSL,但我不确定如何检查文档的不同部分,它实际上将从tableModel / rows / row / columns /列映射到tableModel / columns /列。

我基本上将其输出为CSV。我有代码来附加每个/ tableModel / rows / row / columns / column xml的列信息,但我认为这是不必要的,它使得xm对于Netbeans / Visual Studio来说太大了(大约7MB)。

我想要的输出是:

Date,Name
1-Dec-2010 00:00:00 GMT,Jim
2-Dec-2010 00:00:00 GMT,Jane

非常感谢,

Andez

2 个答案:

答案 0 :(得分:2)

以下内容为您的输入样本

生成所描述的输出
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:param name="sep" select="','"/>
  <xsl:param name="lf" select="'&#10;'"/>

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:apply-templates select="table/columns/column/name"/>
    <xsl:value-of select="$lf"/>
    <xsl:apply-templates select="table/rows/row"/>
  </xsl:template>

  <xsl:template match="column/name">
    <xsl:value-of select="."/>
    <xsl:if test="position() != last()">
      <xsl:value-of select="$sep"/>
    </xsl:if>
  </xsl:template>

  <xsl:template match="rows/row">
    <xsl:apply-templates select="columns/column"/>
    <xsl:value-of select="$lf"/>
  </xsl:template>

  <xsl:template match="row/columns/column[not(localDate)]">
    <xsl:value-of select="value"/>
    <xsl:if test="position() != last()">
      <xsl:value-of select="$sep"/>
    </xsl:if>
  </xsl:template>

  <xsl:template match="row/columns/column[localDate]">
    <xsl:value-of select="localDate"/>
    <xsl:if test="position() != last()">
      <xsl:value-of select="$sep"/>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

但它没有查看相应的列类型,只是输出localDate元素(如果存在)。那够了吗? 还请说明是否可以使用XSLT 2.0(由AltovaXML Tools或Saxon 9实现),这使得这些东西更容易。

[edit]我想在匹配模式中使用一个密钥,虽然在XSLT 1.0中不允许这样做,但它似乎有效,所以以下是您需求的更好实现:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:param name="sep" select="','"/>
  <xsl:param name="lf" select="'&#10;'"/>

  <xsl:key name="k1" match="table/columns/column" use="@id"/>

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:apply-templates select="table/columns/column/name"/>
    <xsl:value-of select="$lf"/>
    <xsl:apply-templates select="table/rows/row"/>
  </xsl:template>

  <xsl:template match="column/name">
    <xsl:value-of select="."/>
    <xsl:if test="position() != last()">
      <xsl:value-of select="$sep"/>
    </xsl:if>
  </xsl:template>

  <xsl:template match="rows/row">
    <xsl:apply-templates select="columns/column"/>
    <xsl:value-of select="$lf"/>
  </xsl:template>

  <xsl:template match="row/columns/column[not(key('k1', @id)/type = 'Date')]">
    <xsl:value-of select="value"/>
    <xsl:if test="position() != last()">
      <xsl:value-of select="$sep"/>
    </xsl:if>
  </xsl:template>

  <xsl:template match="row/columns/column[key('k1', @id)/type = 'Date']">
    <xsl:value-of select="localDate"/>
    <xsl:if test="position() != last()">
      <xsl:value-of select="$sep"/>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

这个不那么冗长但可能......深奥的样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:key name="kDataType" match="type" use="../@id"/>
    <xsl:template match="value|table/*/*/name">
        <xsl:variable name="vIsDateType"
                      select="key('kDataType',../@id)='Date'"/>
        <xsl:value-of
             select="concat(substring(',',
                                      1 div boolean(../preceding-sibling::*)),
                            self::name,
                            self::value[not($vIsDateType)],
                            ../localDate[$vIsDateType],
                            substring('&#xA;',
                                      1 div not(../following-sibling::*)))"/>
    </xsl:template>
    <xsl:template match="text()"/>
</xsl:stylesheet>

输出:

Date,Name
1-Dec-2010 00:00:00 GMT,Jim
2-Dec-2010 00:00:00 GMT,Jane