如何使用XSLT使用元数据转换XML文档?

时间:2012-05-08 19:27:12

标签: xslt

我有一个报告生成器工具,可以为不同类型的报告生成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 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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,美元,

643635,GE.N,GE.USD,美元,

(你需要坚持检查最后一个以删除最后一个逗号。)

答案 2 :(得分: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>

请注意,我只是缩短了名称空间前缀,以便于阅读(和键入)。

答案 3 :(得分: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