如何对xslt中的元素(列)进行排序以将xml文件转换为csv格式

发布于 2024-12-06 14:58:21 字数 1602 浏览 0 评论 0原文

<?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 格式的报告输出中,您将看到 xml 格式中存在所有 50 列,但我还包括通常隐藏在报告中的额外字段。

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

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

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

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

非常感谢任何创建这种 xsl 文件的好主意,非常感谢您理解我的问题并尝试帮助我解决这个问题看待。

<?xml version="1.0" encoding="utf-8"?>
<Report p1:schemaLocation="Customer details  http://reportserver?%2fCustomer details&rs%3aFormat=XML&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>

The above xml is produced by SSRS for the RDL file. I want to transform the above xml file to CSV format using XSLT (customized format).
The RDL file (SSRS report) is very simple with 50 columns, and displays the data for all the columns depending on the user selection on the user interface.
The user interface has got the parameter selection for all the 50 columns (i.e they can select the order of the column, they can select a particular column to be included on the report or not, the fontstyle etc...). As mentioned the each column has 2 main functionalities i.e. they can be sorted and as well ordered by based on the selections.

For example from the report output i.e in the xml format given above you will see all the 50 columns exist on the xml format but I am also including the extra fiedls which are generally hided on the report.

The col1 is included on the report and is ordered (seqID) as the 2nd column on the csv file.
The col2 is also included on the report and is ordered as the 1st column on the csv file.
The col3 is not included on the report and the order selection is empty, so this is not included on the csv file.
...
...
like wise the col50 is included on the report but is ordered in as 3rd column in the csv file.

My main challenge here to create the xslt file for "CSV" and put the columns in the order selection which are selected per user basis.

The output in the CSV file after transformation will look as follows:

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

Any good idea to create this kind of xsl file is much appreciated and I thank you so much for understanding my question and trying to help me in this regard.

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

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

发布评论

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

评论(1

梦里梦着梦中梦 2024-12-13 14:58:21

我。此 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&rs%3aFormat=XML&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。适当使用 substring()name()current()

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

__

number($s) = number($s)

II. 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>	</xsl:text>
     </xsl:for-each>
     <xsl:text>
</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

I. This XSLT 1.0 transformation:

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

when applied on this XML document (the provided one, made well-formed and unambiguous):

<Report
p1:schemaLocation="Customer details  http://reportserver?%2fCustomer details&rs%3aFormat=XML&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>

produces the wanted, correct result:

aaa2,aaa1,aaa50,aaa4

Explanation:

  1. We use that the XPath 1.0 expression:

__

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

is equivalent to the XPath 2.0 expression:

ends-with($s1, $s2))

.2. Appropriate use of <xsl:sort>, substring(), name() and current().

.3. Using the fact that a string $s is castable to number if and only if:

__

number($s) = number($s)

II. XSLT 2.0 solution:

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

when this transformation is applied on the same XML document (above), the same correct result is produced:

aaa2,aaa1,aaa50,aaa4

Update: @desi has asked that the heading should also be generated.

Here is the updated XSLT 1.0 transformation (as indicated, @desi is limited to use XSLT 1.0 only) that does this:

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

When this transformation is applied on the same XML document (above), the wanted, correct result is produced:

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