在 C# 中创建 XML 树 (LINQ to XML)

本文提供有关在 C# 中创建 XML 树的信息。

有关使用 LINQ 查询结果作为 XElement 内容的信息,请参阅函数构造

构造元素

通过 XElementXAttribute 构造函数的签名,可以将元素或属性的内容作为参数传递到构造函数。 由于其中一个构造函数使用可变数目的参数,因此可以传递任意数目的子元素。 当然,这些子元素中的每一个都可以包含它们自己的子元素。 对任意元素,可以添加任意多个属性。

在添加 XNode(包括 XElement)或 XAttribute 对象时,如果新内容没有父级,则直接将这些对象附加到 XML 树中。 如果新内容已经有父级,并且是另一 XML 树的一部分,则克隆新内容,并将新克隆的内容附加到 XML 树。 本文最后一个示例对此进行了演示。

若要创建 contactsXElement,可以使用下面的代码:

XElement contacts =
    new XElement("Contacts",
        new XElement("Contact",
            new XElement("Name", "Patrick Hines"),
            new XElement("Phone", "206-555-0144"),
            new XElement("Address",
                new XElement("Street1", "123 Main St"),
                new XElement("City", "Mercer Island"),
                new XElement("State", "WA"),
                new XElement("Postal", "68042")
            )
        )
    );

如果正确缩进,则构造 XElement 对象的代码十分类似于基础 XML 的结构。

XElement 构造函数

XElement 类使用下面的构造函数用于函数构造。 请注意,对于 XElement,存在其他一些构造函数,但是由于它们不用于函数构造,因此没有在此列出。

构造函数 说明
XElement(XName name, object content) 创建 XElementname 参数指定元素的名称;content 指定元素的内容。
XElement(XName name) 创建一个 XElement,其 XName 初始化为指定名称。
XElement(XName name, params object[] content) 创建一个 XElement,其 XName 初始化为指定名称。 从参数列表的内容创建属性和/或子元素。

content 参数极其灵活。 它支持作为 XElement 的有效子对象的任何类型的对象。 下面的规则适用于在此参数中传递的不同类型的对象:

示例:创建包含内容的 XElement

可以使用单个方法调用来创建一个包含简单内容的 XElement。 为此,请指定内容作为第二个参数,如下所示:

XElement n = new XElement("Customer", "Adventure Works");
Console.WriteLine(n);

该示例产生下面的输出:

<Customer>Adventure Works</Customer>

可以将任意类型的对象作为内容进行传递。 例如,下面的代码创建一个包含浮点数作为内容的元素:

XElement n = new XElement("Cost", 324.50);
Console.WriteLine(n);

该示例产生下面的输出:

<Cost>324.5</Cost>

该浮点数被装箱并传递给构造函数。 装箱的数字转换为字符串,然后用作元素的内容。

示例:创建具有子元素的 XElement

如果传递 XElement 类的一个实例作为内容参数,则构造函数将创建一个具有子元素的元素:

XElement shippingUnit = new XElement("ShippingUnit",
    new XElement("Cost", 324.50)
);
Console.WriteLine(shippingUnit);

该示例产生下面的输出:

<ShippingUnit>
  <Cost>324.5</Cost>
</ShippingUnit>

示例:创建具有多个子元素的 XElement

可以传递多个 XElement 对象作为内容。 每个 XElement 对象都作为子元素包含进来。

XElement address = new XElement("Address",
    new XElement("Street1", "123 Main St"),
    new XElement("City", "Mercer Island"),
    new XElement("State", "WA"),
    new XElement("Postal", "68042")
);
Console.WriteLine(address);

该示例产生下面的输出:

<Address>
  <Street1>123 Main St</Street1>
  <City>Mercer Island</City>
  <State>WA</State>
  <Postal>68042</Postal>
</Address>

将上面的示例扩展,可以创建整个 XML 树,如下所示:

XElement contacts =
    new XElement("Contacts",
        new XElement("Contact",
            new XElement("Name", "Patrick Hines"),
            new XElement("Phone", "206-555-0144"),
            new XElement("Address",
                new XElement("Street1", "123 Main St"),
                new XElement("City", "Mercer Island"),
                new XElement("State", "WA"),
                new XElement("Postal", "68042")
            )
        )
    );
Console.WriteLine(contacts);

该示例产生下面的输出:

<Contacts>
  <Contact>
    <Name>Patrick Hines</Name>
    <Phone>206-555-0144</Phone>
    <Address>
      <Street1>123 Main St</Street1>
      <City>Mercer Island</City>
      <State>WA</State>
      <Postal>68042</Postal>
    </Address>
  </Contact>
</Contacts>

示例:创建包含 XAttribute 的 XElement

如果传递 XAttribute 类的一个实例作为内容参数,则构造函数将创建一个具有属性的元素:

XElement phone = new XElement("Phone",
    new XAttribute("Type", "Home"),
    "555-555-5555");
Console.WriteLine(phone);

该示例产生下面的输出:

<Phone Type="Home">555-555-5555</Phone>

示例:创建一个空元素

若要创建空 XElement,请不要将任何内容传递给构造函数。 下面的示例创建一个空元素:

XElement n = new XElement("Customer");
Console.WriteLine(n);

该示例产生下面的输出:

<Customer />

示例:附加与克隆

前面提到,在添加 XNode(包括 XElement)或 XAttribute 对象时,如果新内容没有父级,则直接将这些对象附加到 XML 树。 如果新内容已经有父级,并且是另一 XML 树的一部分,则克隆新内容,并将新克隆的内容附加到 XML 树。

以下示例演示将有父级的元素添加到树中,以及将没有父级的元素添加到树中时的行为。

// Create a tree with a child element.
XElement xmlTree1 = new XElement("Root",
    new XElement("Child1", 1)
);

// Create an element that's not parented.
XElement child2 = new XElement("Child2", 2);

// Create a tree and add Child1 and Child2 to it.
XElement xmlTree2 = new XElement("Root",
    xmlTree1.Element("Child1"),
    child2
);

// Compare Child1 identity.
Console.WriteLine("Child1 was {0}",
    xmlTree1.Element("Child1") == xmlTree2.Element("Child1") ?
    "attached" : "cloned");

// Compare Child2 identity.
Console.WriteLine("Child2 was {0}",
    child2 == xmlTree2.Element("Child2") ?
    "attached" : "cloned");

// This example produces the following output:
//    Child1 was cloned
//    Child2 was attached

另请参阅