I am new to XML and tried the following but I'm getting an exception. Can someone help me?
The exception is This operation would create an incorrectly structured document
My code:
string strPath = Server.MapPath("sample.xml");
XDocument doc;
if (!System.IO.File.Exists(strPath))
{
doc = new XDocument(
new XElement("Employees",
new XElement("Employee",
new XAttribute("id", 1),
new XElement("EmpName", "XYZ"))),
new XElement("Departments",
new XElement("Department",
new XAttribute("id", 1),
new XElement("DeptName", "CS"))));
doc.Save(strPath);
}
Xml document must have only one root element. But you are trying to add both Departments and Employees nodes at root level. Add some root node to fix this:
doc = new XDocument(
new XElement("RootName",
new XElement("Employees",
new XElement("Employee",
new XAttribute("id", 1),
new XElement("EmpName", "XYZ"))),
new XElement("Departments",
new XElement("Department",
new XAttribute("id", 1),
new XElement("DeptName", "CS"))))
);
You need to add root element.
doc = new XDocument(new XElement("Document"));
doc.Root.Add(
new XElement("Employees",
new XElement("Employee",
new XAttribute("id", 1),
new XElement("EmpName", "XYZ")),
new XElement("Departments",
new XElement("Department",
new XAttribute("id", 1),
new XElement("DeptName", "CS")))));
In my case I was trying to add more than one XElement to xDocument which throw this exception. Please see below for my correct code which solved my issue
string distributorInfo = string.Empty;
XDocument distributors = new XDocument();
XElement rootElement = new XElement("Distributors");
XElement distributor = null;
XAttribute id = null;
distributor = new XElement("Distributor");
id = new XAttribute("Id", "12345678");
distributor.Add(id);
rootElement.Add(distributor);
distributor = new XElement("Distributor");
id = new XAttribute("Id", "22222222");
distributor.Add(id);
rootElement.Add(distributor);
distributors.Add(rootElement);
distributorInfo = distributors.ToString();
Please see below for what I get in distributorInfo
<Distributors>
<Distributor Id="12345678" />
<Distributor Id="22222222" />
</Distributors>
Related
I am generating a XML file with hundreds of thousands of elements and the runtime of my code is currently over 3 minutes! I have tried both XDocument and XmlDocument to see if either would decrease the runtime; XDocument was better, but only by a small margin. Is there anything else I can try?
Code
string path = Server.MapPath("~/Temp/employee.xml");
XDocument d = new XDocument(new XElement("Employees"));
d.Declaration = new XDeclaration("1.0", "utf-8", "true");
while (reader.Read())
{
d.Root.Add(new XElement("Employee",
new XElement("LastName", reader["lastname"].ToString()),
new XElement("FirstName", reader["firstname"].ToString()),
new XElement("MiddleInitial", reader["middleini"].ToString()),
new XElement("ID", reader["id"].ToString()),
new XElement("Title", reader["title"].ToString()),
new XElement("DOB", reader["title"].ToString()),
new XElement("Category", reader["category"].ToString()),
new XElement("Supervisor", reader["supervisor"].ToString()),
new XElement("CurrentAddress", reader["address1"].ToString()),
new XElement("Address", reader["address2"].ToString()),
new XElement("City", reader["city"].ToString()),
new XElement("State", reader["state"].ToString()),
new XElement("ZipCode", reader["zip"].ToString()),
new XElement("OfficePhone", reader["office_phone"].ToString()),
new XElement("HomePhone", reader["home_phone"].ToString()),
new XElement("Email", reader["email_address"].ToString()),
new XElement("DateHired", reader["chem_employment_date"].ToString()),
new XElement("DateTerminated", reader["emp_terminate_date"].ToString()),
new XElement("StatusCode", reader["status_code"].ToString()),
new XElement("Room", reader["room"].ToString()),
new XElement("IsPrivate", reader["isprivate"].ToString()),
new XElement("Floor", reader["floor"].ToString()),
new XElement("Wing", reader["wing"].ToString()),
new XElement("InRoster", reader["isroster"].ToString()),
new XElement("RosterCategory", reader["roster_category"].ToString()),
new XElement("LastModified", reader["lastmodified"].ToString()),
new XElement("ShowReport", reader["isbudget"].ToString()),
new XElement("ModifiedBy", reader["lastmodifiedby"].ToString())
));
d.Save(path);
}
Try using the xmlwriter class
https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlwriter?view=net-5.0
C# export of large datatbase to XML
XmlWriter uses less memory than XmlDocument, but you will have to write the entire document from scratch each time.
I have the following structure in an xml:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfNO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<No>
<Id>1</Id>
<Name>txt_1</Name>
<Text>some text</Text>
<Txt_relacionados>
<string>txt_4</string>
<string>txt_4</string>
<string>txt_4</string>
</Txt_relacionados>
<N>0</N>
<X>285</X>
<Y>31</Y>
<Externa>false</Externa>
<EM>false</EM>
<B>false</B>
<K>false</K>
<L1>false</L1>
<L2>false</L2>
<L3>false</L3>
<L4>false</L4>
<L5>false</L5>
<L6>false</L6>
<L7>false</L7>
<L8>false</L8>
<L9>false</L9>
<L10>false</L10>
<L11>false</L11>
<L12>false</L12>
<IP>0</IP>
</No>
I'm having trouble inserting the "Txt_relacionados" element because it contains a list of strings.
In the VO of this element i have the following:
[XmlArray("Txt_relacionados"), XmlArrayItem("string", Type = typeof(String))]
private List<String> txt_relacionados = new List<String>();
public List<String> Txt_relacionados
{
get { return txt_relacionados; }
set { txt_relacionados = value; }
}
What changes should I make in the code below to be able to insert this list?
public void inserir2(VoNo value)
{
RefreshXDoc();
XElement no = XElement.Load(path);
XElement element = new XElement("No",
new XElement("Id", value.Id),
new XElement("Name", value.Name),
new XElement("Text", value.Text),
new XmlArrayAttribute("Txt_relacionados", value.Txt_relacionados),
new XElement("N", value.N),
new XElement("X", value.X),
new XElement("Y", value.Y),
new XElement("Externa", value.Externa),
new XElement("B", value.B),
new XElement("K", value.K),
new XElement("L1", value.L1),
new XElement("L2", value.L2),
new XElement("L3", value.L3),
new XElement("L4", value.L4),
new XElement("L5", value.L5),
new XElement("L6", value.L6),
new XElement("L7", value.L7),
new XElement("L8", value.L8),
new XElement("L9", value.L9),
new XElement("L10", value.L10),
new XElement("L11", value.L11),
new XElement("L12", value.L12),
new XElement("IP", value.IP));
no.Add(element);
no.Save(path);
}
Thanks!!
You need to create Txt_relacionados element before you create new element No and then pass Txt_relacionados at proper place when you are creating No.
Consider following.
public void inserir2(VoNo value)
{
var rels = new XElement("Txt_relacionados");
foreach (var x in value.Txt_relacionados)
{
var elem = new XElement("string", x);
rels.Add(elem);
}
RefreshXDoc();
XElement no = XElement.Load(path);
XElement element = new XElement("No",
new XElement("Id", value.Id),
new XElement("Name", value.Name),
new XElement("Text", value.Text),
rels,
new XElement("N", value.N),
new XElement("X", value.X),
new XElement("Y", value.Y),
new XElement("Externa", value.Externa),
new XElement("B", value.B),
new XElement("K", value.K),
new XElement("L1", value.L1),
new XElement("L2", value.L2),
new XElement("L3", value.L3),
new XElement("L4", value.L4),
new XElement("L5", value.L5),
new XElement("L6", value.L6),
new XElement("L7", value.L7),
new XElement("L8", value.L8),
new XElement("L9", value.L9),
new XElement("L10", value.L10),
new XElement("L11", value.L11),
new XElement("L12", value.L12),
new XElement("IP", value.IP));
no.Add(element);
no.Save(path);
}
I am trying to build an XML document using Linq, XElement and data from Database,
It's working kinda, but in my XML, I want to close the tag and start a new tag and get the results from the query to populate into for the Tag, it is complaining that my variable r in the tag is unresolved, how can I make this work, or is there a better way of building the XML. All the child elements should be under the parent , having two children and , which has their own set of children.
Here is the code below
public void GenerateXML(int id, string site, string state, string country, string bFn, string bLn, string sFn, string sLn)
{
var results = (from o in _db.Orders
where o.OrderId == id
select o).ToList();
var xmlDoc = new XElement("Order",
from r in results
select
new XElement("OrderHeader",
new XElement("SiteId", site),
new XElement("OrderId", r.OrderId),
new XElement("Time", r.OrderDate.Value),
new XElement("Subtotal", r.SubTotal),
new XElement("Shipping", ""),
new XElement("SalesTax", r.SalesTax),
new XElement("Total", r.Total),
new XElement("PaymentAmount", ""),
new XElement("PaymentMethod", ""),
new XElement("ArchiTypeAcctNum", "20001"),
new XElement("TaxExempt", r.TaxExempt),
new XElement("SpecialInstructions", r.SpecialInstructions),
new XElement("BillTo",
new XElement("BillEmail", r.BillToEmail),
new XElement("FirstName", bFn),
new XElement("LastName", bLn),
new XElement("CompanyName", r.BillCompany),
new XElement("Address1", r.BillToAddress),
new XElement("City", r.BillToCity),
new XElement("State", state),
new XElement("Country", country),
new XElement("Zip", r.BillToZip),
new XElement("Phone", r.BillToPhoneNumber)),
new XElement("ShipTo",
new XElement("FirstName", sFn),
new XElement("LastName", sLn),
new XElement("CompanyName", r.ShipCompany),
new XElement("Address1", r.ShipToAddress),
new XElement("City", r.ShipToCity),
new XElement("State", state),
new XElement("Country", country),
new XElement("Zip", r.ShipToZip),
new XElement("Phone", r.ShipToPhoneNumber))),
new XElement("Items",
from i in r.Items
select new XElement("Item",
new XElement("SKU", i.SkuNumber),
new XElement("PROD_Name", i.ProductName),
new XElement("Description", i.Description),
new XElement("Attributes", i.Attributes),
new XElement("Quantity", i.Quantity),
new XElement("UnitPrice", i.UnitPrice),
new XElement("InkColor", i.InkColor)))
);
xmlDoc.Save(Server.MapPath(#"~/Xml/Orders.xml"));
RedirectToAction("Save");
}
I wrote an extension for same purpose. I think much easier . you can just use as orders.EntityToXml();
public static class XmlExtensions
{
public static bool EntityToXml<T>(this T entity, string filePath)
{
if (string.IsNullOrEmpty(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
var dir = Path.GetDirectoryName(filePath);
if (string.IsNullOrEmpty(dir))
{
throw new ArgumentNullException(nameof(filePath));
}
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var serializer= new System.Xml.Serialization.XmlSerializer(typeof(T));
using (var stream = new StreamWriter(filePath))
{
serializer.Serialize(stream , entity);
return true;
}
}
}
How to add the collection of items to XML Document ? Something I started trying, but it's wrong! I'll be grateful for the link on the Internet at a good tutorial too. Also, It is assumed that the iteration will be some elements.
Such code:
public static void Create_Interfaces()
{
XDocument Interfaces;
Interfaces = XDocument.Load("Interfaces.xml");
List<string> intf = new List<string>{"em0","em1","em2"};
foreach (var i in intf)
{
Interfaces = new XDocument(
new XElement("Interfaces",
new XElement("Interface",
new XElement("name", i),
new XElement("vlan-tagging", XElement.EmptySequence),
new XElement("unit",
new XElement("vlan-id", "10"),
new XElement("family", new XElement("inet", new XElement("address", new XElement("name", "10.10.1.23/24"))))))));
}
Interfaces.Save("Interfaces.xml");
}
Get your root element add new elements to it then save it:
var rootElement = Interfaces.Root;
foreach (var i in intf)
{
var element = new XElement("Interface",
new XElement("name", i),
new XElement("vlan-tagging", XElement.EmptySequence),
new XElement("unit",
new XElement("vlan-id", "10"),
new XElement("family",
new XElement("inet",
new XElement("address",
new XElement("name", "10.10.1.23/24"))))));
rootElement.Add(element);
}
rootElement.Save("Interfaces.xml");
I have a dictionary with key value pair. I want to write it to XML using LINQ.
I am able to create the XML document using LINQ but not sure how to read the values from dictionary & write into the XML.
Following is the example with hardcode values to generate XML, I want to ready the dictionary instead of hardcode values
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "true"),
new XElement("countrylist",
new XElement("country",
new XAttribute("id", "EMP001"),
new XAttribute("name", "EMP001")
),
new XElement("country",
new XAttribute("id", "EMP001"),
new XAttribute("name", "EMP001")
)
)
);
If the id attribute is stored as dictionary key and the name as value, you can use the following
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "true"),
new XElement("countrylist",
dict.Select(d => new XElement("country",
new XAttribute("id", d.Key),
new XAttribute("name", d.Value))))
);
Assuming you have a Country class with an Id and a Name and the countries are stored as values in your dictionary countries, with the id beeing the key:
XDocument xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "true"));
var xCountryList = new XElement("countrylist");
foreach(var kvp in countries)
xCountryList.Add(new XElement("country",
new XAttribute("id", kvp.Key),
new XAttribute("name", kvp.Value.Name)));
Here dude with the dictionary
Dictionary<int, string> fooDictionary = new Dictionary<int, string>();
fooDictionary.Add(1, "foo");
fooDictionary.Add(2, "bar");
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "true"),
new XElement("countrylist")
);
var countryList = doc.Descendants("countrylist").Single(); // Get Country List Element
foreach (var bar in fooDictionary) {
// Add values per item
countryList.Add(new XElement("country",
new XAttribute("id", bar.Key),
new XAttribute("name", bar.Value)));
}