2

我有一个报告生成器工具,可以为不同类型的报告生成 XML 文档。这些 XML 文档中的每一个都有一组字段(以下 XML 文档中的报告:列),用于描述其中的实际数据(以下 XML 文档中的报告:行)。由于字段列表是动态的并且对于每种报告都在不断变化,因此如何编写使用“字段”将数据转换为 csv 文件的通用 XSL 模板。

我的示例 XML 文档:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<reporting:root xmlns:reporting="http://www.something.net/reporting">

  <reporting:default0 reporting:type="Portfolio">
    <reporting:header>      
      <reporting:configuration>
        <reporting:columns>
          <reporting:column reporting:group="instrument" reporting:name="Ident" reporting:tag="ident" reporting:type="int"/>
          <reporting:column reporting:group="prices" reporting:name="Last (Time)" reporting:tag="lastTime" reporting:type="string"/>
          <reporting:column reporting:group="noGroup" reporting:name="RIC" reporting:tag="ric" reporting:type="string"/>
          <reporting:column reporting:group="instrument" reporting:name="Reference" reporting:tag="reference" reporting:type="string"/>
         <reporting:column reporting:group="result" reporting:name="Currency" reporting:tag="currency" reporting:type="string"/>          
        </reporting:columns>
     </reporting:configuration>      
    </reporting:header>
    <reporting:window reporting:Id="36674" reporting:level="0" reporting:name="MY_PORTFOLIO" reporting:parentId="11991">
      <reporting:line reporting:Id="67520135" reporting:level="1" reporting:name="INTERNATIONAL BUSINESS MACHINES CORP" reporting:parentId="36674" reporting:positionType="0">
        <reporting:ident>643633</reporting:ident>        
        <reporting:reference>IBM.USD</reporting:reference>
        <reporting:currency>USD</reporting:currency>        
      </reporting:line>
     <reporting:line reporting:Id="67520179" reporting:level="1" reporting:name="GENERAL ELECTRIC CO" reporting:parentId="36674" reporting:positionType="0">
        <reporting:ident>643635</reporting:ident>
        <reporting:ric>GE.N</reporting:ric>
        <reporting:reference>GE.USD</reporting:reference>
        <reporting:currency>USD</reporting:currency>        
     </reporting:line>
    </reporting:window>
  </reporting:default0>
</reporting:root>

我需要看到格式如下的输出:

ident,lastTime,ric,reference,currency
643633,,,IBM.USD,USD
643635,,GE.N,GE.USD,USD

我做了一些工作,但它完成了一半。找不到如何处理“动态”字段列表并将它们用作描述实际数据的标签。

有人可以帮忙吗?

谢谢。

4

4 回答 4

1

在 XSLT 中有多种方法可以解决这个问题,但我认为最优雅和可维护的方法是编写一个样式表来处理给定的源文档,并输出一个 XSLT 样式表来进行实际报告。我已经看到这种方法在许多项目中非常成功地使用。

于 2012-05-08T20:08:45.787 回答
0

尝试

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:r="http://www.something.net/reporting">
    <xsl:output method="text" version="1.0"/>
    <xsl:template match="/">
        <xsl:for-each select="/r:root/r:default0/r:header/r:configuration/r:columns/r:column">
            <xsl:value-of select="@r:tag"/>
            <xsl:if test="position() != last()">,</xsl:if>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
        <xsl:for-each select="/r:root/r:default0/r:window/r:line">
            <xsl:variable name="POSITION" select="position()"/>
            <xsl:for-each select="//r:root/r:default0/r:header/r:configuration/r:columns/r:column">
                <xsl:variable name="TAGNAME" select="@r:tag"/><xsl:value-of select="//r:line[$POSITION]/*[local-name()=$TAGNAME]"/><xsl:if test="position() != last()">,</xsl:if>
            </xsl:for-each>
            <xsl:text>&#xA;</xsl:text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

请注意,我只是缩短了命名空间前缀以使其更易于阅读(和键入)。

于 2012-05-08T21:57:50.837 回答
0
<xsl:output method="text"/>

<xsl:template match="/">

    <xsl:for-each select="/*:root/*:default0/*:header/*:configuration/*:columns/*:column">
        <xsl:value-of select="@reporting:tag"/>
        <xsl:text>,</xsl:text>
    </xsl:for-each>
    <xsl:for-each select="/*:root/*:default0/*:window/*:line">
        <xsl:variable name="theline"  select="."/>
        <xsl:text>&#x0a;</xsl:text>

        <xsl:for-each select="/*:root/*:default0/*:header/*:configuration/*:columns/*:column" >
            <xsl:variable name="oname"  select="@reporting:tag" />
              <xsl:value-of select="$theline/*[local-name()=$oname]" /><xsl:text>,</xsl:text>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

将产生:

ident,lastTime,ric,参考,货币,

643633,,,IBM.USD,USD,

643635,,GE.N,GE.USD,USD,

(你需要坚持检查最后一个去掉最后的逗号。)

于 2012-05-08T21:42:03.617 回答
0

这个简短而简单的转换:

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

 <xsl:variable name="vColNames" select="/*/*/r:header/*/*/*/@r:tag"/>

 <xsl:template match="/">
  <xsl:for-each select="$vColNames">
   <xsl:value-of select="concat(., ',')"/>
  </xsl:for-each>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="r:line">
  <xsl:variable name="vThis" select="."/>
  <xsl:text>&#xA;</xsl:text>
  <xsl:for-each select="$vColNames">
    <xsl:if test="position() > 1">,</xsl:if>
    <xsl:apply-templates select="$vThis/*[local-name() = current()]"/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

在提供的 XML 文档上运行时:

<reporting:root xmlns:reporting="http://www.something.net/reporting">

  <reporting:default0 reporting:type="Portfolio">
    <reporting:header>
      <reporting:configuration>
        <reporting:columns>
          <reporting:column reporting:group="instrument" reporting:name="Ident" reporting:tag="ident" reporting:type="int"/>
          <reporting:column reporting:group="prices" reporting:name="Last (Time)" reporting:tag="lastTime" reporting:type="string"/>
          <reporting:column reporting:group="noGroup" reporting:name="RIC" reporting:tag="ric" reporting:type="string"/>
          <reporting:column reporting:group="instrument" reporting:name="Reference" reporting:tag="reference" reporting:type="string"/>
         <reporting:column reporting:group="result" reporting:name="Currency" reporting:tag="currency" reporting:type="string"/>
        </reporting:columns>
     </reporting:configuration>
    </reporting:header>
    <reporting:window reporting:Id="36674" reporting:level="0" reporting:name="MY_PORTFOLIO" reporting:parentId="11991">
      <reporting:line reporting:Id="67520135" reporting:level="1" reporting:name="INTERNATIONAL BUSINESS MACHINES CORP" reporting:parentId="36674" reporting:positionType="0">
        <reporting:ident>643633</reporting:ident>
        <reporting:reference>IBM.USD</reporting:reference>
        <reporting:currency>USD</reporting:currency>
      </reporting:line>
     <reporting:line reporting:Id="67520179" reporting:level="1" reporting:name="GENERAL ELECTRIC CO" reporting:parentId="36674" reporting:positionType="0">
        <reporting:ident>643635</reporting:ident>
        <reporting:ric>GE.N</reporting:ric>
        <reporting:reference>GE.USD</reporting:reference>
        <reporting:currency>USD</reporting:currency>
     </reporting:line>
    </reporting:window>
  </reporting:default0>
</reporting:root>

产生想要的正确结果

ident,lastTime,ric,reference,currency,
643633,,,IBM.USD,USD
643635,,GE.N,GE.USD,USD
于 2012-05-09T13:14:13.173 回答