C#在XML中添加节点错误:“此操作将创建结构错误的文档。”

时间:2018-10-16 16:03:59

标签: c# xml linq-to-xml

XML-1

<CurrentStatus>
    <Time Stamp= "12:30">
        <price>100</price>
        <amount>1</amount>
    </Time>

    <Time Stamp= "14:50">
        <price>10</price>
        <amount>5</amount>
    </Time> 

    <Time Stamp= "16:30">
        <price>10</price>
        <amount>5</amount>
    </Time>     
</CurrentStatus>

XML-2

<CurrentStatus>
    <Time Stamp= "17:22">
        <price>40</price>
        <amount>120</amount>
    </Time>               
</CurrentStatus>

我首先阅读XML-1,然后尝试将XML-2中的 Time 节点插入其中(XML-1):

//Read first XML
XDocument xDoc1 = XDocument.Load(@"D:\myfile1.xml");

//Read second XML
XDocument xDoc2 = XDocument.Load(@"D:\myfile2.xml");
XElement currentTimeNode = xDoc2.Descendants("Time").ToList()[0]; //first decendent
//Append data
xDoc1.AddFirst(currentTimeNode); //This line throws ERROR

问题::我想将节点添加为第一个子节点(添加Time节点的完整块)。第xDoc1.AddFirst(currentTimeNode);行引发以下错误:

  

此操作将创建结构错误的文档。

2 个答案:

答案 0 :(得分:1)

您正在尝试将currentTimeNode添加为xDoc1的子项-但是xDoc1是XML文档本身,这意味着您尝试将currentTimeNode添加为第二XML root element。但是,格式正确的XML文档必须仅具有一个根元素,因此xDoc1.AddFirst(currentTimeNode)会引发您所看到的异常,因为它已经具有根元素<CurrentStatus>

相反,您应该将currentTimeNode添加到xDoc1的先前存在的Root中:

xDoc1.Root.AddFirst(currentTimeNode);

或者,如果xDoc1.Root可能为空(因为您是从头开始在内存中构造它的,而不是从先前存在的文件中加载),则可以有条件地对其进行分配:

if (xDoc1.Root == null)
    xDoc1.Add(new XElement("CurrentStatus"));
xDoc1.Root.AddFirst(currentTimeNode);

顺便说一句,将ToList()[0]替换为First()可能更简单,更高效,因为一旦返回第一个元素,First()就不会尝试枚举和具体化整个查询:

var currentTimeNode = xDoc2.Descendants("Time").First(); //first decendent

提琴here

答案 1 :(得分:0)

FWIW-对于可能遇到此问题的VB员工而言。

    Dim xe1 As XElement
    Dim xe2 As XElement

    xe1 = <CurrentStatus>
              <Time Stamp="12:30">
                  <price>100</price>
                  <amount>1</amount>
              </Time>

              <Time Stamp="14:50">
                  <price>10</price>
                  <amount>5</amount>
              </Time>

              <Time Stamp="16:30">
                  <price>10</price>
                  <amount>5</amount>
              </Time>
          </CurrentStatus>

    xe2 = <CurrentStatus>
              <Time Stamp="17:22">
                  <price>40</price>
                  <amount>120</amount>
              </Time>
          </CurrentStatus>

    xe1.Add(xe2.<Time>) 'add to end
    ' OR
    ' xe1.AddFirst(xe2.<Time>) 'first