当数据集WriteXml()函数生成xml文件时,C#如何使用XDocument类更新xml文件

Posted

技术标签:

【中文标题】当数据集WriteXml()函数生成xml文件时,C#如何使用XDocument类更新xml文件【英文标题】:C# How to update xml file using XDocument class when xml file generated by dataset WriteXml() function 【发布时间】:2021-09-19 14:46:24 【问题描述】:

我正在寻找一些指导方针,如何使用XDocument 更新我的复杂 XML。 XML 看起来很复杂,因为它是从DataSet.WriteXml() 生成的

这是我的 XML 首先是由QCSavedData.WriteXml(@strQCViewAllPath); QCSavedData 生成的数据集:

<?xml version="1.0" standalone="yes"?>
<HNNMY_ViewAll>
    <dgvViewAll_Vertical>
        <Section_x0020_>MS</Section_x0020_>
        <LineItem>Morgan Stanley</LineItem>
        <Revise_x0020_Date>10-09-2020</Revise_x0020_Date>
        <_x0032_010_x0020_FYA>126,966.0000</_x0032_010_x0020_FYA>
        <_x0032_011_x0020_FYA>128,810.0000</_x0032_011_x0020_FYA>
        <_x0032_012_x0020_FYA>140,948.0000</_x0032_012_x0020_FYA>
        <_x0032_013_x0020_FYA>150,090.0000</_x0032_013_x0020_FYA>
        <_x0031_Q_x0020_2014A>37,524.0000</_x0031_Q_x0020_2014A>
        <_x0032_Q_x0020_2014A>44,181.0000</_x0032_Q_x0020_2014A>
        <_x0033_Q_x0020_2014A>45,259.0000</_x0033_Q_x0020_2014A>
        <_x0034_Q_x0020_2014A>49,656.0000</_x0034_Q_x0020_2014A>
        <_x0032_014_x0020_FYA>176,620.0000</_x0032_014_x0020_FYA>
        <_x0031_Q_x0020_2015A>46,791.0000</_x0031_Q_x0020_2015A>
        <_x0032_Q_x0020_2015A>53,233.0000</_x0032_Q_x0020_2015A>
        <_x0033_Q_x0020_2015A>53,420.0000</_x0033_Q_x0020_2015A>
        <_x0034_Q_x0020_2015A>56,477.0000</_x0034_Q_x0020_2015A>
        <_x0032_015_x0020_FYA>209,921.0000</_x0032_015_x0020_FYA>
        <_x0031_Q_x0020_2016A>50,624.0000</_x0031_Q_x0020_2016A>
        <_x0032_Q_x0020_2016A>54,341.0000</_x0032_Q_x0020_2016A>
        <_x0033_Q_x0020_2016A>56,802.0000</_x0033_Q_x0020_2016A>
        <GroupKey>Consensus Model~Total Revenue Including VAT~RD_001~NBM~~1~MS</GroupKey>
    </dgvViewAll_Vertical>
</HNNMY_ViewAll>

    看到这是&lt;Section_x0020_&gt;MS&lt;/Section_x0020_&gt;如何查询当section是MS,因为Section有x0020

    看到这个 &lt;_x0032_010_x0020_FYA&gt;126,966.0000&lt;/_x0032_010_x0020_FYA&gt; 数据表有很多列,如 2010 FYA、2011 FYA .... 1Q 2014A 但是当数据表数据保存在 xml 中时,它会以这种方式显示 &lt;_x0032_010_x0020_FYA&gt;126,966.0000&lt;/_x0032_010_x0020_FYA&gt; 那么我该如何更新这个标签内的值?

    看到这个&lt;GroupKey&gt;Consensus Model~Total Revenue Including VAT~RD_001~NBM~~1~MS&lt;/GroupKey&gt;

我必须这样查询

XDocument 表示当 Section == GroupKey.Split('~')[5] AND Column Name is 2010 FYA 然后更新 内部的值>column 2010 FYA 表示该列的值 &lt;_x0032_010_x0020_FYA&gt;126,966.0000&lt;/_x0032_010_x0020_FYA&gt;

请帮助我提供指导我如何更新 XML 的示例代码。

【问题讨论】:

它复杂的唯一原因是您的数据集列名有空格并且以数字开头。 xml 标签不允许第一个字符是数字,也不允许标签名称中包含空格。 先生,您能否分享一些想法如何使用 xdocument 类更新我的 xml 数据。 您需要修复列名或使用“AS”将名称映射到其他内容。您使用什么查询来获取数据? 【参考方案1】:

DataSet 写入XML 时,输出将显示在DataTable.WriteXml() 的文档中。它看起来像:

<DataSetName>  
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <!--Schema information here, if you have requested it -->
  </xs:schema>  
  <!--The first table: -->
  <Table1Name>  <!--This repeats for every row in Table1 -->
    <!-- Column values -->
    <Column1Name>Value 1.1</Column1Name>  
    <Column2Name>Value 2.1</Column2Name>  
  </Table1Name>  
  <Table1Name> 
    <!-- Column values -->
    <Column1Name>Value 1.2</Column1Name>  
    <Column2Name>Value 2.2</Column2Name>  
  </Table1Name>  
  <!--The second table: -->
  <Table2Name>  <!--This repeats for every row in Table2 -->
    <!-- Column values -->
    <ColumnName>Value</ColumnName>  
  </Table2Name>  
  <!--And the remaining tables if any follow sequentially -->
</DataSetName>  

请注意,数据集、表和列名变成了 XML 元素名。但是,并非每个字符串都可以用作格式良好的 XML 元素名称,该名称由 XML standard 定义。稍微简化一下,格式良好的元素名称必须:

以 Unicode 字母或 _ 开头。 随后由 Unicode 字母数字字符组成,_-.

因此2010 FYA 不能是格式正确的 XML 元素名称,因为它以数字字符开头并包含空格。因此,在这种情况下,框架使用XmlConvert.EncodeLocalName(String) 将任意字符串编码为格式良好的 XML 名称:

此方法与EncodeName 方法类似,不同之处在于它对冒号字符进行编码,从而保证名称可以用作命名空间限定名称的本地名称部分。

以及相关的XmlConvert.EncodeName(String)

此方法转换无效字符,例如空格或半角片假名,需要在不支持或不存在模式的情况下映射到 XML 名称。无效字符被转换为转义的数字实体编码。

转义字符是“_”。任何不符合XML 1.0 spec (fourth edition) 建议的 XML 名称字符都将转义为 xHHHH。 HHHH 字符串代表最高有效位第一顺序中字符的四位十六进制 UCS-2 代码。例如,名称 Order Details 编码为 Order_x0020_Details。

下划线字符不需要转义,除非它后面跟着一个字符序列,在解码名称时,该字符序列与下划线一起可能被误解为转义序列。例如,Order_Details 未编码,但 Order_x0020_ 编码为 Order_x005f_x0020_。不允许使用简写形式。例如,x20 和 __ 的形式不会生成。

如果您想使用数据集、表或列名称查询 XML,您必须调用 XmlConvert.EncodeLocalName(name) 来确定 XML 中使用的名称。反之,如果要查询从 XML 中读取的某个元素名称的数据集,则必须调用 XmlConvert.DecodeName(String) 重新生成原始名称。

例如要更新某些XDocument xdocument 中的2010 FYA 列,您可以这样做:

var tableName = XmlConvert.EncodeLocalName("dgvViewAll_Vertical"); // EncodeLocalName is not strictly needed here since dgvViewAll_Vertical happens to be a well-formed XML name
var sectionName = XmlConvert.EncodeLocalName("Section ");
var groupKeyName = XmlConvert.EncodeLocalName("GroupKey"); // EncodeLocalName is not strictly needed here since GroupKey happens to be a well-formed XML name
var columnName = XmlConvert.EncodeLocalName("2010 FYA");

var columnValue = "New Value";

var ns = xdocument.Root.Name.Namespace;
var columns = xdocument.Root
    .Elements(ns + tableName)
    // Add error handling here when groupKeyName is not found or not in the expected syntax
    .Where(e => e.Element(ns + sectionName)?.Value == e.Element(ns + groupKeyName).Value.Split('~').Last()) 
    .Select(e => e.Element(ns + columnName));

foreach (var column in columns)

    column.Value = columnValue;

请注意,此代码假定您的 data set、data tables 和 data columns 都使用相同的 XML 命名空间(上面代码中的 ns)。对于您的问题中显示的 XML,这是正确的。如果不是这样,则在查询表名和列名时需要使用适当的命名空间。

演示小提琴here.

【讨论】:

以上是关于当数据集WriteXml()函数生成xml文件时,C#如何使用XDocument类更新xml文件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用自定义 XSD 架构编写 XML?

.net怎样把sql2005数据库表中的内容生成xml文件?

将 XML 文件读入 C# DataSet 的问题

DataSet.WriteXml 到字符串

从数据库中导出 XML 文件并在实际列之前获得没有任何属性的干净格式

dom写xml