如何以可读的格式显示WriteXml中的DataTable XML?

时间:2011-09-02 11:42:40

标签: c# .net xml xslt datatable

我有一些DataTables要导出到文件然后查看。我可以使用DataTable.WriteXml()将DataTables的内容输出到XML,但是以表格形式显示这些数据的简单方法是什么?

一种建议的方法是使用XSLT或类似的方法将XML转换为可读的内容。我不知道这是否容易,但如果它易于使用,那将是一个很好的解决方案。

下面是我从WriteXml()获取单个DataTable的XML示例。这是一个名为'RecentMatter'的表,包含10列和3行数据。我希望它显示为数据表。我不太关心数据值的格式化,例如将DateTime值转换为更易读的值。生成它时我使用了XmlWriteMode.WriteSchema参数。如果删除它,则删除所有架构信息(在第一个标记之前)。

不同的表显然会有不同数量的列,因此任何解决方案都需要处理它,理想情况下无需修改具有不同列的表的解决方案。

<NewDataSet>
<xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="NewDataSet">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="RecentMatter" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="RecentMatter">
<xs:complexType>
<xs:sequence>
<xs:element name="UserLogin">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="MatterNumber">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ClientName">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="MatterName">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ClientCode" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="OfficeCode" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="OfficeName" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Billable" type="xs:boolean"/>
<xs:element name="ReferenceId" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="2147483647"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="LastUsed" type="xs:dateTime"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//RecentMatter"/>
<xs:field xpath="UserLogin"/>
<xs:field xpath="MatterNumber"/>
</xs:unique>
</xs:element>
</xs:schema>

<RecentMatter>
  <UserLogin>PSLTP6\RJK</UserLogin>
  <MatterNumber>99999-2302</MatterNumber>
  <ClientName>Test Matters</ClientName>
  <MatterName>DP Test Matter</MatterName>
  <ClientCode>99999</ClientCode>
  <OfficeCode/>
  <OfficeName/>
  <Billable>true</Billable>
  <ReferenceId/>
  <LastUsed>2011-08-23T23:40:24.13+01:00</LastUsed>
</RecentMatter>
<RecentMatter>
  <UserLogin>PSLTP6\RJK</UserLogin>
  <MatterNumber>999991.0002</MatterNumber>
  <ClientName>Lathe 1</ClientName>
  <MatterName>LW Test 2</MatterName>
  <ClientCode/>
  <OfficeCode/>
  <OfficeName/>
  <Billable>true</Billable>
  <ReferenceId/>
  <LastUsed>2011-07-12T16:57:27.173+01:00</LastUsed>
</RecentMatter>
<RecentMatter>
  <UserLogin>PSLTP6\RJK</UserLogin>
  <MatterNumber>999991-0001</MatterNumber>
  <ClientName>Lathe 1</ClientName>
  <MatterName>LW Test 1</MatterName>
  <ClientCode/>
  <OfficeCode/>
  <OfficeName/>
  <Billable>false</Billable>
  <ReferenceId/>
  <LastUsed>2011-07-12T01:59:06.887+01:00</LastUsed>
</RecentMatter>
</NewDataSet>

2 个答案:

答案 0 :(得分:5)

给它一个机会。可能是将DataTable序列化为XML的最简单方法:

DataTable table = new DataTable();    
System.IO.StringWriter writer = new System.IO.StringWriter();

//notice that we're ignoring the schema so we get clean XML back
//you can change the write mode as needed to get your result
table.WriteXml(writer, XmlWriteMode.IgnoreSchema, false);

string dataTableXml = writer.ToString();

至于以可读格式显示它,我建议将XML传递给XSL转换器,然后您可以使用它来解析XML并根据需要操作输出。


将XSLT转换应用于数据集

http://msdn.microsoft.com/en-us/library/8fd7xytc%28v=vs.71%29.aspx#Y289

这是我创建的一个简单示例,用于解释如何使用XSL转换器。我没有测试过,但它应该非常接近:

DataSet ds = new DataSet();
StringBuilder sbXslOutput = new StringBuilder();

using (XmlWriter xslWriter = XmlWriter.Create(sbXslOutput))
{
    XslCompiledTransform transformer = new XslCompiledTransform();
    transformer.Load("transformer.xsl");
    XsltArgumentList args = new XsltArgumentList();

    transformer.Transform(new XmlDataDocument(ds), args, xslWriter);
}

string dataSetHtml = sbXslOutput.ToString();

使用XSLT将XML格式化为HTML

这是使用XSLT将XML转换为HTML表的示例。它应该相当容易采用,因此您可以将它与序列化的DataSet一起使用。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/">
      <table border="1">
        <tr>
          <th>User Login</th>
          <th>Matter Number</th>
          ...
        </tr>
        <xsl:for-each select="NewDataSet/RecentMatter">
          <tr>
            <td>
              <xsl:value-of select="UserLogin"/>
            </td>
            <td>
              <xsl:value-of select="MatterNumber"/>
            </td>
            ...
          </tr>
        </xsl:for-each>
      </table>
  </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

我建的这个方法可能对你有用(如果你愿意,可以删除破折号装饰......)。它应该像这样呈现表:

+----------+----------+----------+
| Column1  | Column2  | Column3  |
+----------+----------+----------+
| asdfasdf | asdfasdf | asdfasdf |
| asdfasdf | asdfasdf | asdfasdf |
| asdfasdf | asdfasdf | asdfasdf |
+----------+----------+----------+

以下是代码:

public void WriteTable(DataTable table, Stream outputStream)
{
    // Create writer
    StreamWriter writer = new StreamWriter(outputStream);

    // Compute max lengths to build correct tabular columns
    Dictionary<string, int> maxLengths = new Dictionary<string, int>();

    foreach (DataColumn column in table.Columns)
    {
        maxLengths.Add(column.ColumnName, column.ColumnName.Length);

        foreach (DataRow row in table.Rows)
        {
            maxLengths[column.ColumnName] = Math.Max(
                maxLengths[column.ColumnName], 
                Convert.ToString(row[column.ColumnName]).Length);
        }
    }

    // Build horizontal rule to separate headers from data
    string horizontalRule = "+";

    foreach (DataColumn column in table.Columns)
    {
        horizontalRule += String.Format("-{0}-+", new string('-', maxLengths[column.ColumnName]));
    }

    writer.WriteLine(horizontalRule);

    // Write headers
    writer.Write("|");

    foreach (DataColumn column in table.Columns)
    {
        writer.Write(" {0," + (-(maxLengths[column.ColumnName])) + "} |", column.ColumnName);
    }

    writer.WriteLine();

    writer.WriteLine(horizontalRule);

    // Write data
    foreach (DataRow row in table.Rows)
    {
        writer.Write("|");

        foreach (DataColumn column in table.Columns)
        {
            writer.Write(" {0," + (-(maxLengths[column.ColumnName])) + "} |", row[column.ColumnName]);
        }

        writer.WriteLine();
    }

    writer.WriteLine(horizontalRule);

    // Close writer
    writer.Close();
}