Best .net Method to create an XML Doc

2020-05-23 02:46发布

I am trying to figure out what the best method is for writing an XML Document. Below is a simple example of what I am trying to create off of data I am pulling from our ERP system. I have read about XMLWriter, but thought I would see if there are any other better methods. Any suggestions would be greatly appreciated.

Example 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条回答
Juvenile、少年°
2楼-- · 2020-05-23 02:55

If your use case is simple, nothing could possibly simpler and easier to use than XmlTextWriter. That said, one alternative would be to use an XmlDocument object to create and append all of your nodes. But I think it's easier to write and maintain code that uses XmlTextWriter if you're creating a document from scratch rather than manipulating one. Using XmlTextWriter should be very straightforward:

        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();
查看更多
闹够了就滚
3楼-- · 2020-05-23 02:56

I would suggest using the classes in System.Xml.Linq.dll which contain an XML DOM API that allows for easy build-up of XML structures due to the way the contructors are designed. Trying to create an XML structure using the System.Xml classes is very painful because you have to create them detached then separately add them into the document.

Here's an example of XLinq vs. System.Xml to create a DOM from scratch. Your eyes will bleed when you see the System.Xml example.

Here's a quick example of how you would use XLinq to build up part of your doc.

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

TIP Although it's a little unorthodox (though no worse than some of the language butchering that has become popular lately), I have on occasion used C#'s type aliasing feature to minimize the code even further:

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")
    )
);
查看更多
We Are One
4楼-- · 2020-05-23 02:57
// 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);
查看更多
ら.Afraid
5楼-- · 2020-05-23 02:59

I found it largely depends how complex your original data is.

If your data is nicely organized in objects and it is sufficient to dump it in XML, Linq is very verbose and powerful. But as soon as there are object inter-dependencies, I don't think you want to go with the Linq one-liner, as this is real pain to debug and/or extend.

For those cases, I'd prefer to go with XmlDocument, create a help method to facilitate adding attributes to an element (see below), and use Linq in foreach loops around the XML creation blocks.

private void XAttr(ref XmlNode xn, string nodeName, string nodeValue)
{
    XmlAttribute result = xn.OwnerDocument.CreateAttribute(nodeName); 
    result.InnerText = nodeValue;
    xn.Attributes.Append(result);
}
查看更多
等我变得足够好
6楼-- · 2020-05-23 03:04

There's a new language called XCST that compiles to 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>
查看更多
看我几分像从前
7楼-- · 2020-05-23 03:08

What about this : create a class "Order" and one "Orders", and then serialize those out to XML - seems a lot easier to me than creating the XML bit by bit from hand....

Since you say you're pulling the data off your ERP, you probably already have objects and classes for "Order" and so on - maybe it's sufficient to put a few [XmlElement] attributes on your classes and you're good to go!

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; }
    }
}

and in your main app something like this:

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);
}

Working with objects and then serializing them out to disk seems a lot easier to me than fiddling around with XDocument and other APIs.

查看更多
登录 后发表回答