You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# DataSet.ReadXml读取XML返回行结构异常 未生成预期列结构

问题描述

我正尝试使用DataSet的ReadXml方法从XML文件创建DataTable,但始终无法正确定义Schema以正确解析目标文件。
问题根源在于XML的嵌套结构设计:本应作为列名的ColumnUid是节点值而非元素名称。
当前方法返回的DataTable结构错误:
错误表结构
期望得到的目标表结构:
正确表结构
我想确认是否可以通过为ReadXml传入正确定义的Schema实现该需求?虽然可以在初次读取后通过LINQ或循环转置DataTable得到目标结构,但更希望避免这类后续处理。

精简后的XML示例

<?xml version="1.0" encoding="utf-16"?>
<DataTable Uid="dtDocRows">
 <Rows>
    <Row>
     <Cells>
    <Cell>
      <ColumnUid>DocEntry</ColumnUid>
      <Value>121496</Value>
    </Cell>
    <Cell>
      <ColumnUid>DocNum</ColumnUid>
      <Value>264803</Value>
    </Cell>
    <Cell>
      <ColumnUid>LineNum</ColumnUid>
      <Value>0</Value>
    </Cell>
    <Cell>
      <ColumnUid>ItemCode</ColumnUid>
      <Value>BENIGRAMST55060075L</Value>
    </Cell>       
    <Cell>
      <ColumnUid>Quantity</ColumnUid>
      <Value>1.000000</Value>
    </Cell>   
  </Cells> 
</Row>
<Row>
  <Cells>
    <Cell>
      <ColumnUid>DocEntry</ColumnUid>
      <Value>121658</Value>
    </Cell>
    <Cell>
      <ColumnUid>DocNum</ColumnUid>
      <Value>264965</Value>
    </Cell>
    <Cell>
      <ColumnUid>LineNum</ColumnUid>
      <Value>0</Value>
    </Cell>
    <Cell>
      <ColumnUid>ItemCode</ColumnUid>
      <Value>PYCCHANT202575L</Value>
    </Cell>      
    <Cell>
      <ColumnUid>Quantity</ColumnUid>
      <Value>1.000000</Value>
    </Cell>       
  </Cells>
</Row>

当前使用的C#函数代码

private DataTable getDotNetDataTable()
{
    DataSet ds = new DataSet();
    XDocument xdoc = XDocument.Parse(dtDocRows.SerializeAsXML(SAPbouiCOM.BoDataTableXmlSelect.dxs_DataOnly));
    xdoc.Save(@"C:\1\xml\test.xml");
    ds.ReadXml(@"C:\1\xml\test.xml");
    return ds.Tables.Item(4);

    return dt;
}

答案

ReadXml不支持这种「将节点值动态映射为列名」的结构解析,就算传入自定义XSD Schema也无法实现,因为XSD只能定义固定的元素/属性与列的映射关系,无法把动态变化的节点值转换为列名。
不需要读取后再做整表转置,直接在读取前用LINQ to XML把源XML转换成ReadXml能识别的标准结构即可,转换逻辑非常轻量:

private DataTable getDotNetDataTable()
{
    // 直接加载序列化得到的XML,无需存本地文件
    XDocument xdoc = XDocument.Parse(dtDocRows.SerializeAsXML(SAPbouiCOM.BoDataTableXmlSelect.dxs_DataOnly));
    
    // 结构转换:将每个Row下的Cell节点转为「ColumnUid值为元素名、Value值为元素值」的标准节点
    var transformedRows = xdoc.Descendants("Row")
        .Select(row => 
            new XElement("Row", 
                row.Descendants("Cell")
                   .Select(cell => new XElement(
                       cell.Element("ColumnUid")?.Value, 
                       cell.Element("Value")?.Value
                   ))
            )
        );
    
    // 构造ReadXml可直接识别的标准XML结构
    XDocument standardFormatXml = new XDocument(
        new XElement("DataSetRoot", transformedRows)
    );
    
    DataTable targetTable = new DataTable();
    // 直接读取转换后的XML流,自动生成匹配预期的列结构和行数据
    targetTable.ReadXml(standardFormatXml.CreateReader());
    return targetTable;
}

转换后的XML每个<Row>节点下直接挂载<DocEntry>121496</DocEntry>、<DocNum>264803</DocNum>这类节点,ReadXml会自动将节点名识别为列名、节点值识别为对应行的字段值,读取出的表结构完全符合预期,不需要后续额外处理。
该方案自动兼容不同行存在不同字段的场景,ReadXml会自动把所有出现过的ColumnUid建成列,对应行缺失该字段时值为DBNull。


内容的提问来源于stack exchange,提问作者Praxiom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 02:57:20