C# Adding node in XML error: "This operation would create an incorrectly structured document."

C# Adding node in XML error: "This operation would create an incorrectly structured document."

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,然后尝试将 Time 节点从 XML-2 插入其中( 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); 行抛出以下错误:

This operation would create an incorrectly structured document.

您正在尝试将 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] with First() 可能更简单、性能更高,因为一旦返回第一个元素,First() 将不会尝试枚举和具体化整个查询:

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

示例 fiddle here.

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