最好的.net方法来创建XML文档

问题描述 投票:15回答:11

我试图找出编写XML文档的最佳方法。下面是我试图从我的ERP系统中提取数据的一个简单示例。我已阅读有关XMLWriter的内容,但我想我会看看是否还有其他更好的方法。任何建议将不胜感激。

示例XML:

<?xml version="1.0"?>
<Orders>
  <Order OrderNumber="12345">
    <ItemNumber>0123993587</ItemNumber>
    <QTY>10</QTY>
    <WareHouse>PA019</WareHouse>
  </Order>
  <Order OrderNumber="12346">
    <ItemNumber>0123993587</ItemNumber>
    <QTY>9</QTY>
    <WareHouse>PA019</WareHouse>
  </Order>
  <Order OrderNumber="12347">
    <ItemNumber>0123993587</ItemNumber>
    <QTY>8</QTY>
    <WareHouse>PA019</WareHouse>
  </Order>
</Orders>
c# .net xml
11个回答
27
投票

Josh的回答显示了在LINQ to XML中创建单个元素是多么容易......它没有显示创建多个元素也非常容易。假设你有一个名为List<Order>orders ...你可以像这样创建整个文档:

var xml = new XElement("Orders",
    orders.Select(order =>
        new XElement("Order",
            new XAttribute("OrderNumber", order.OrderNumber),
            new XElement("ItemNumber", order.ItemNumber),
            new XElement("QTY", order.Quantity),
            new XElement("Warehouse", order.Warehouse)
        ));
);

LINQ to XML使得构建XML非常容易。它也支持XML命名空间,这也非常简单。例如,如果您希望元素位于特定的命名空间中,您只需要:

XNamespace ns = "http://your/namespace/here";
var xml = new XElement(ns + "Orders",
    orders.Select(order =>
        new XElement(ns + "Order",
... (rest of code as before)

LINQ to XML是我使用过的最好的XML API ...它也非常适合查询。


0
投票

我发现它在很大程度上取决于原始数据的复杂程度。

如果您的数据在对象中组织得很好并且将其转储为XML就足够了,Linq非常冗长且功能强大。但是只要有对象相互依赖,我就不认为你想要使用Linq单行,因为这是调试和/或扩展的真正痛苦。

对于这些情况,我更喜欢使用XmlDocument,创建一个帮助方法以便于向元素添加属性(参见下文),并在围绕XML创建块的foreach循环中使用Linq。

private void XAttr(ref XmlNode xn, string nodeName, string nodeValue)
{
    XmlAttribute result = xn.OwnerDocument.CreateAttribute(nodeName); 
    result.InnerText = nodeValue;
    xn.Attributes.Append(result);
}

-2
投票

您只需右键单击代码窗口,选择InsertSnippet,然后单击此链接

 Data-Xml.....>Xml>Xmlcreate

它非常容易


9
投票

我建议使用System.Xml.Linq.dll中的类,它们包含一个XML DOM API,由于构造器的设计方式,它允许轻松构建XML结构。尝试使用System.Xml类创建XML结构非常痛苦,因为您必须创建它们分离然后单独将它们添加到文档中。

XLinq与System.Xml的Here's an example从头开始创建DOM。当您看到System.Xml示例时,您的眼睛会流血。

这是一个快速示例,说明如何使用XLinq构建部分文档。

var xml = new XElement("Orders",
    new XElement("Order",
        new XAttribute("OrderNumber", 12345),
        new XElement("ItemNumber", "01234567"),
        new XElement("QTY", 10),
        new XElement("Warehouse", "PA019")
    )
);

提示虽然它有点非正统(虽然不比最近流行的一些语言屠宰更糟糕),但我偶尔使用C#的类型别名功能来进一步减少代码:

using XE = System.Xml.Linq.XElement;
using XA = System.Xml.Linq.XAttribute;
...
var xml = new XE("Orders",
    new XE("Order",
        new XA("OrderNumber", 12345),
        new XA("ItemNumber", "01234567"),
        new XA("QTY", 10),
        new XA("Warehouse", "PA019")
    )
);

4
投票

那么:创建一个类“Order”和一个“Orders”,然后将它们序列化为XML - 对我而言比从手工创建XML更容易....

既然你说你正在从你的ERP中提取数据,那么你可能已经有了“Order”的对象和类等等 - 也许只需要在你的类上放几个[XmlElement]属性就可以了!

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace XmlLinqTest
{
    [Serializable]
    [XmlRoot(Namespace = "")]
    public class Orders
    {
        private List<Order> _orders = new List<Order>();

        /// <remarks/>
        [XmlElement("Order")]
        public List<Order> OrderList
        {
            get { return _orders; }
        }
    }

    /// <remarks/>
    [Serializable]
    public class Order
    {
        /// <remarks/>
        [XmlElement]
        public string ItemNumber { get; set; }

        [XmlElement]
        public int QTY { get; set; }

        /// <remarks/>
        [XmlElement]
        public string WareHouse { get; set; }

        /// <remarks/>
        [XmlAttribute]
        public string OrderNumber { get; set; }
    }
}

并在您的主应用程序中这样的事情:

Orders orders = new Orders();

Order work = new Order() { ItemNumber = "0123993587", OrderNumber = "12345", QTY = 10, WareHouse = "PA019" };
orders.OrderList.Add(work);

work = new Order() { ItemNumber = "0123993587", OrderNumber = "12346", QTY = 9, WareHouse = "PA019" };
orders.OrderList.Add(work);

work = new Order() { ItemNumber = "0123993587", OrderNumber = "12347", QTY = 8, WareHouse = "PA019" };
orders.OrderList.Add(work);

XmlSerializer ser = new XmlSerializer(typeof(Orders));

using(StreamWriter wr = new StreamWriter(@"D:\testoutput.xml", false, Encoding.UTF8))
{
    ser.Serialize(wr, orders);
}

使用对象然后将它们序列化到磁盘似乎比摆弄XDocument和其他API要容易得多。


2
投票

如果您的用例很简单,那么没有什么比XmlTextWriter更简单,更容易使用了。也就是说,一种替代方法是使用XmlDocument对象来创建和附加所有节点。但是,如果您从头开始创建文档而不是操作文档,我认为编写和维护使用XmlTextWriter的代码更容易。使用XmlTextWriter应该非常简单:

        StringBuilder output = new StringBuilder();
        XmlWriter writer = XmlWriter.Create(output);
        writer.WriteProcessingInstruction("xml", "version=\"1.0\"");
        writer.WriteStartElement("Orders");
        //...start loop...
        writer.WriteStartElement("Order");
        writer.WriteAttributeString("OrderNumber", "12345");
        writer.WriteElementString("ItemNumber", "0123993587");
        writer.WriteElementString("QTY", "10");
        writer.WriteElementString("WareHouse", "PA019");
        writer.WriteEndElement();
        //...loop...
        writer.WriteEndElement();
        writer.Close();

1
投票

有一种叫做XCST的新语言编译成C#。

<c:template name='c:initial-template' expand-text='yes'>
   <c:param name='orders' as='IEnumerable&lt;Order>'/>

   <Orders>
      <c:for-each name='order' in='orders'>
         <Order OrderNumber='{order.Number}'>
            <ItemNumber>{order.ItemNumber}</ItemNumber>
            <QTY>{order.Quantity}</QTY>
            <WareHouse>{order.WareHouse}</WareHouse>
         </Order>
      </c:for-each>
   </Orders>
</c:template>

0
投票

我必须创建以下XML文档,其中一部分参数化。

<?xml version="1.0" encoding="utf-8"?>
<wap-provisioningdoc>
  <characteristic type="BOOTSTRAP">
    <parm name="NAME" value="SYNCSETTINGS" />
  </characteristic>
  <characteristic type="APPLICATION">
    <parm name="APPID" value="w5" />
    <parm name="TO-NAPID" value="INTERNET" />
    <parm name="NAME" value="SYNCSETTINGS" />
    <parm name="ADDR" value="http://syncserver/sync" />
    <characteristic type="RESOURCE">
      <parm name="URI" value="pb" />
      <parm name="NAME" value="Contacts DB" />
      <parm name="AACCEPT" value="text/x-vcard" />
    </characteristic>
    <characteristic type="RESOURCE">
      <parm name="URI" value="cal" />
      <parm name="NAME" value="Calendar DB" />
      <parm name="AACCEPT" value="text/x-vcalendar" />
    </characteristic>
    <characteristic type="RESOURCE">
      <parm name="URI" value="notes" />
      <parm name="NAME" value="Notes DB" />
      <parm name="AACCEPT" value="text/plain" />
    </characteristic>
    <characteristic type="APPAUTH">
      <parm name="AAUTHNAME" value="username" />
      <parm name="AAUTHSECRET" value="password" />
    </characteristic>
  </characteristic>
</wap-provisioningdoc>

这是我使用单个LINQ语句执行此操作的代码。

请注意,使用LINQ创建上面的XML文档并将其保存到XML文件会保留XML文档格式并保留换行符和回车符,从而使文档正确制表。

public string CreateOTAXmlFile(string Username, string Password)
    {
        var ota = new XDocument(
                    new XElement("wap-provisioningdoc",
                        new XElement("characteristic", new XAttribute("type", "BOOTSTRAP"),
                            new XElement("parm", new XAttribute("name", "NAME"), new XAttribute("value", "SYNCSETTINGS"))
                                    ),
                        new XElement("characteristic", new XAttribute("type", "APPLICATION"),
                            new XElement("parm", new XAttribute("name", "APPID"), new XAttribute("value", "w5")),
                            new XElement("parm", new XAttribute("name", "TO-NAPID"), new XAttribute("value", "INTERNET")),
                            new XElement("parm", new XAttribute("name", "NAME"), new XAttribute("value", "SYNCSETTINGS")),
                            new XElement("parm", new XAttribute("name", "ADDR"), new XAttribute("value", "http://syncserver/sync")),
                            new XElement("characteristic", new XAttribute("type", "RESOURCE"),
                                new XElement("parm", new XAttribute("name", "URI"), new XAttribute("value", "pb")),
                                new XElement("parm", new XAttribute("name", "NAME"), new XAttribute("value", "Contacts DB")),
                                new XElement("parm", new XAttribute("name", "AACCEPT"), new XAttribute("value", "text/x-vcard"))
                                        ),
                            new XElement("characteristic", new XAttribute("type", "RESOURCE"),
                                new XElement("parm", new XAttribute("name", "URI"), new XAttribute("value", "cal")),
                                new XElement("parm", new XAttribute("name", "NAME"), new XAttribute("value", "Calendar DB")),
                                new XElement("parm", new XAttribute("name", "AACCEPT"), new XAttribute("value", "text/x-vcalendar"))
                                        ),
                            new XElement("characteristic", new XAttribute("type", "RESOURCE"),
                                new XElement("parm", new XAttribute("name", "URI"), new XAttribute("value", "notes")),
                                new XElement("parm", new XAttribute("name", "NAME"), new XAttribute("value", "Notes DB")),
                                new XElement("parm", new XAttribute("name", "AACCEPT"), new XAttribute("value", "text/plain"))
                                        ),
                            new XElement("characteristic", new XAttribute("type", "APPAUTH"),
                                new XElement("parm", new XAttribute("name", "AAUTHNAME"), new XAttribute("value", Username)),
                                new XElement("parm", new XAttribute("name", "AAUTHSECRET"), new XAttribute("value", Password))
                                        )
                                    )
                                )
                            );

        ota.Save(Server.MapPath("~/OTA/") + Username + ".xml");
        return (ota.ToString());

    }

0
投票
// Create the xml document containe
XmlDocument doc = new XmlDocument();// Create the XML Declaration, and append it to XML document
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
doc.AppendChild(dec);// Create the root element
XmlElement root = doc.CreateElement("Library");
doc.AppendChild(root);
// Create Books
// Note that to set the text inside the element,
// you use .InnerText instead of .Value (which will throw an exception).
// You use SetAttribute to set attribute
XmlElement book = doc.CreateElement("Book");
book.SetAttribute("BookType", "Hardcover");
XmlElement title = doc.CreateElement("Title");
title.InnerText = "Door Number Three";
XmlElement author = doc.CreateElement("Author");
author.InnerText = "O'Leary, Patrick";
book.AppendChild(title);
book.AppendChild(author);
root.AppendChild(book);
book = doc.CreateElement("Book");
book.SetAttribute("BookType", "Paperback");
title = doc.CreateElement("Title");
title.InnerText = "Lord of Light";
author = doc.CreateElement("Author");
author.InnerText = "Zelanzy, Roger";
book.AppendChild(title);
book.AppendChild(author);
root.AppendChild(book);
string xmlOutput = doc.OuterXml;
The same code but using an XMLWriter to a memory stream.

XmlWriterSettings wSettings = new XmlWriterSettings();
wSettings.Indent = true;
MemoryStream ms = new MemoryStream();
XmlWriter xw = XmlWriter.Create(ms, wSettings);// Write Declaration
xw.WriteStartDocument();
// Write the root node
xw.WriteStartElement("Library");
// Write the books and the book elements
xw.WriteStartElement("Book");
xw.WriteStartAttribute("BookType");
xw.WriteString("Hardback");
xw.WriteEndAttribute();
xw.WriteStartElement("Title");
xw.WriteString("Door Number Three");
xw.WriteEndElement();
xw.WriteStartElement("Author");
xw.WriteString("O'Leary, Patrick");
xw.WriteEndElement();
xw.WriteEndElement();
// Write another book
xw.WriteStartElement("Book");
xw.WriteStartAttribute("BookType");
xw.WriteString("Paperback");
xw.WriteEndAttribute();
xw.WriteStartElement("Title");
xw.WriteString("Lord of Light");
xw.WriteEndElement();
xw.WriteStartElement("Author");
xw.WriteString("Zelanzy, Roger");
xw.WriteEndElement();
xw.WriteEndElement();
// Close the document
xw.WriteEndDocument();
// Flush the write
xw.Flush();
Byte[] buffer = new Byte[ms.Length];
buffer = ms.ToArray();
string xmlOutput = System.Text.Encoding.UTF8.GetString(buffer);

0
投票

如果你不想(或不能)使用LINQ to XML,既不复制你的Order类以包含XML序列化,并认为XmlWriter太冗长,你可以使用简单的经典XmlDocument类:

// consider Order class that data structure you receive from your ERP system
List<Order> orders = YourERP.GetOrders();
XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("Orders"));
foreach (Order order in orders)
{
    XmlElement item = xml.CreateElement("Order");
    item.SetAttribute("OrderNumber", order.OrderNumber);
    item.AppendChild(xml.CreateElement("ItemNumber")).Value = order.ItemNumber;
    item.AppendChild(xml.CreateElement("QTY"       )).Value = order.Quantity;
    item.AppendChild(xml.CreateElement("WareHouse" )).Value = order.WareHouse;
    xml.DocumentElement.AppendChild(item);
}

0
投票

在这个帖子中有很多好的建议,但是没有提到过:使用DataSetReadXml方法定义ADO WriteXml和序列化/反序列化。这可以是一个非常简单和有吸引力的解决方案您的XML格式不正确,但它很接近。

© www.soinside.com 2019 - 2024. All rights reserved.