2
<?xml version="1.0" encoding="utf-8"?>
<Report p1:schemaLocation="Customer details  http://reportserver?%2fCustomer details&amp;rs%3aFormat=XML&amp;rc%3aSchema=True" Name="Customer details" xmlns:p1="http://www.w3.org/2001/XMLSchema-instance" xmlns="Customer details">
  <table2>
   <Detail_Collection>
         <Detail Col1="aaa" col1_SeqID="2"  col1_Include="1"
                 Col2="aaa" col2_SeqID="1"  col2_Include="1"
                 Col3="aaa" col3_SeqID=""  col3_Include="0"
                 Col4="aaa" col4_SeqID="4"  col4_Include="1"
                 Col5="aaa" col5_SeqID=""  col5_Include="0"
                 ... ... ...
                 ... ... ...
                 ... ... ...
                 Col50="aaa" col50_SeqID="3"  col50_Include="1"
                 />
   <Detail_Collection>
</table2>
</Report>

上面的 xml 是 SSRS 为 RDL 文件生成的。我想使用 XSLT(自定义格式)将上述 xml 文件转换为 CSV 格式。RDL 文件(SSRS 报告)非常简单,有 50 列,并根据用户界面上的用户选择显示所有列的数据。用户界面有所有 50 列的参数选择(即,他们可以选择列的顺序,他们可以选择是否包含在报告中的特定列,字体样式等...)。如前所述,每列有 2 个主要功能,即它们可以根据选择进行排序和排序。

例如,从上面给出的 xml 格式的报告输出中,您将看到所有 50 列都以 xml 格式存在,但我还包括通常隐藏在报告中的额外字段。

col1 包含在报告中,并作为 csv 文件的第二列排序 (seqID)。col2 也包含在报告中,并作为 csv 文件的第一列排序。col3 不包含在报告中,并且订单选择为空,因此不包含在 csv 文件中。... ... 同样,col50 包含在报告中,但在 csv 文件中作为第 3 列排序。

我在这里的主要挑战是为“CSV”创建 xslt 文件并将列放在按用户选择的顺序选择中。

转换后 CSV 文件中的输出将如下所示:

Col2    Col1    Col50   Col4
 ...  ...       ...     ....

非常感谢创建这种 xsl 文件的任何好主意,非常感谢您理解我的问题并在这方面为我提供帮助。

4

1 回答 1

1

I. 这个 XSLT 1.0 转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:c="Customer details">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="c:Detail">
     <xsl:apply-templates select=
      "@*[substring(name(), string-length(name())-5)
         = '_SeqID'
        and
          number(.) = number(.)
          ]
     ">
      <xsl:sort data-type="number"/>
     </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:if test="not(position()=1)">,</xsl:if>
  <xsl:value-of select=
    "../@*
       [name()
       =
        concat('Col',substring-before(substring(name(current()),4),'_'))
        ]"/>
 </xsl:template>
</xsl:stylesheet>

当应用于此 XML 文档(提供的文档,格式正确且明确)时:

<Report
p1:schemaLocation="Customer details  http://reportserver?%2fCustomer details&amp;rs%3aFormat=XML&amp;rc%3aSchema=True"
Name="Customer details"
xmlns:p1="http://www.w3.org/2001/XMLSchema-instance"
xmlns="Customer details">
    <table2>
        <Detail_Collection>
            <Detail Col1="aaa1" col1_SeqID="2"  col1_Include="1"
            Col2="aaa2" col2_SeqID="1"  col2_Include="1"
            Col3="aaa3" col3_SeqID=""  col3_Include="0"
            Col4="aaa4" col4_SeqID="4"  col4_Include="1"
            Col5="aaa5" col5_SeqID=""  col5_Include="0"
            Col50="aaa50" col50_SeqID="3"  col50_Include="1"
            />
        </Detail_Collection>
    </table2>
</Report>

产生想要的正确结果

aaa2,aaa1,aaa50,aaa4

说明

  1. 我们使用 XPath 1.0 表达式:

__

substring($s1, string-length($s1) - string-length($s2) +1) = $s2

等效于 XPath 2.0 表达式:

ends-with($s1, $s2))

.2. 正确使用<xsl:sort>substring()和。name()current()

.3. 使用字符串可转换为数字的事实$s当且仅当:

__

number($s) = number($s)

二、XSLT 2.0 解决方案

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:c="Customer details">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>    

 <xsl:template match="c:Detail">
         <xsl:apply-templates select=
          "@*[ends-with(name(),'_SeqID')
            and . castable as xs:integer]">
          <xsl:sort  select="xs:integer(.)"/>
         </xsl:apply-templates>
 </xsl:template>
 <xsl:template match="@*">
      <xsl:if test="not(position()=1)">,</xsl:if>
      <xsl:value-of select=
        "../@*
           [name()
           eq
            concat('Col',translate(name(current()),'col_SeqID',''))]"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一个 XML 文档(如上)时,会产生相同的正确结果

aaa2,aaa1,aaa50,aaa4

更新:@desi 要求也应该生成标题。

这是执行此操作的更新后的 XSLT 1.0 转换(如所示,@desi 仅限于使用 XSLT 1.0):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:c="Customer details">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="c:Detail">

     <xsl:for-each select=
      "@*[substring(name(), string-length(name())-5)
         = '_SeqID'
        and
          number(.) = number(.)
          ]
        ">
        <xsl:sort data-type="number"/>

       <xsl:value-of select=
       "concat('Col',
               substring-before(substring(name(current()),4),
                                '_')
               )
       "/>

          <xsl:text>&#9;</xsl:text>
     </xsl:for-each>
     <xsl:text>&#10;</xsl:text>

     <xsl:apply-templates select=
      "@*[substring(name(), string-length(name())-5)
         = '_SeqID'
        and
          number(.) = number(.)
          ]
     ">
      <xsl:sort data-type="number"/>
     </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:if test="not(position()=1)">,</xsl:if>
  <xsl:value-of select=
    "../@*
       [name()
       =
        concat('Col',substring-before(substring(name(current()),4),'_'))
        ]"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一个 XML 文档(如上)时,会产生所需的正确结果

Col2    Col1    Col50   Col4    
aaa2,aaa1,aaa50,aaa4
于 2011-09-25T03:23:05.227 回答