I am trying to generate an XML using XDocument by pulling data from a DataTable at runtime. I want to have the output in this format:
<Document>
<Alphabets>
<Data>
<Capital>AAA</Capital>
<Small>aaa</Small>
</Data>
</Alphabets>
<Language>
<Name>English</Name>
</Language>
<Alphabets>
<Data>
<Capital>BBB</Capital>
<Small>bbb</Small>
</Data>
</Alphabets>
<Language>
<Name>English</Name>
</Language>
</Document>
The Language element has to be present after every Alphabets element. I have tried very hard to achieve this but I am unable to put this Alphabets tag after every Language element. What I have achieved is this, where the Language element is falling inside Alphabets element:
<Document>
<Alphabets>
<Data>
<Capital>AAA</Capital>
<Small>aaa</Small>
</Data>
<Language>
<Name>English</Name>
</Language>
</Alphabets>
<Alphabets>
<Data>
<Capital>BBB</Capital>
<Small>bbb</Small>
</Data>
<Language>
<Name>English</Name>
</Language>
</Alphabets>
</Document>
Here is my code :
static void Main(string[] args)
{
DataTable dtAlpha = new DataTable("Alphabetss");
dtAlpha.Columns.Add("Capital", typeof(string));
dtAlpha.Columns.Add("Small", typeof(string));
dtAlpha.Rows.Add("AAA", "aaa");
dtAlpha.Rows.Add("BBB", "bbb");
XDocument doc = new XDocument(
new XDeclaration("1.0", "UTF-8", null),
new XElement("Document",
from row in dtAlpha.AsEnumerable()
select new XElement("Alphabets",
new XElement("Data",
new XElement("Capital", row.Field<string>("Capital")),
new XElement("Small", row.Field<string>("Small"))
),
new XElement("Language",
new XElement("Name", "English")
)))
);
Console.WriteLine(doc.ToString());
Console.ReadKey();
}
Please help me on this.
You can try this way :
XDocument doc = new XDocument(
new XDeclaration("1.0", "UTF-8", null),
new XElement("Document")
);
foreach(var row in dtAlpha.AsEnumerable())
{
var alphabets = new XElement("Alphabets",
new XElement("Data",
new XElement("Capital", row.Field<string>("Capital")),
new XElement("Small", row.Field<string>("Small"))
)
);
var language = new XElement("Language",
new XElement("Name", "English")
);
doc.Root.Add(alphabets);
doc.Root.Add(language);
}
Related
I am new to C# and Linq. I am trying to write my Dictionary to file as XML. Therefore I use a foreach loop add all XElements to a root XElement. This is added to the document. But it does only add the last iteration of my loop to the document. What am I doing wrong?
Here is the code
public void ToXml(string xmlFile)
{
//Dictionary used: Values
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", null));
XElement xRoot = new XElement("RootElement");
doc.Add(xRoot);
Dictionary<double, double[]>.KeyCollection keys = Values.Keys;
foreach(double key in keys)
{
XElement inner = new XElement("InnerElement",
new XAttribute("value", key),
new XElement("TestValue1", Values[key][0]),
new XElement("Testvalue2", Values[key][1]),
new XElement("TestValue3", Values[key][2]),
new XElement("TestValue4", Values[key][3]),
new XElement("TestValue5", Values[key][4]),
new XElement("TestValue6", Values[key][5]));
xRoot.Add(inner);
}
doc.Save(xmlFile);
}
This is the output:
<?xml version="1.0" encoding="utf-8"?>
<RootElement>
<InnerElement value="400">
<TestValue1>0</TestValue1>
<Testvalue2>0</Testvalue2>
<TestValue3>200</TestValue3>
<TestValue4>0</TestValue4>
<TestValue5>100</TestValue5>
<TestValue6>491</TestValue6>
</InnerElement>
</RootElement>
i am very new to this. Hope someone could help me suggest how to improve the code.
I have two tables where i need to get the SQL data and ouput it into XML format. I am using LINQ method. Below how the code looks like.
#region Database XML Methods
private static void CreateDatabaseXml(string path)
{
tbchrDataContext db = new tbchrDataContext();
XDocument doc = new XDocument(
// XML Declaration
new XDeclaration("1.0", "utf-8", "yes"),
// XML Root element to 3rd in nest
new XElement(ns + "WMS",
new XElement(ns + "Order",
new XElement(ns + "Header", from a in db.T_ORDER_DETAILs
select new XElement(ns + "RARefNum", a.RARefNum),
new XElement (ns + "WMSCategory", from b in db.T_ORDER_HEADERs select b.Customer),
new XElement (ns + "CustomerID", from a in db.T_ORDER_DETAILs select a.SupplierName)))) );
#endregion
doc.Save(path);
}
And below how is the output of XML looks like.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<WMS xmlns="http://blog.cripperz.sg">
<Order>
<Header>
<RARefNum>RASO000001</RARefNum>
<RARefNum>RASO000001</RARefNum>
<WMSCategory>ESSVMI</WMSCategory>
<CustomerID>nVidianVidia</CustomerID>
</Header>
</Order>
</WMS>
Ultimately i wanted to achieve the below XML, some of the data grab from SQL is from two separate tables in one XML nest / element.
<?xml version="1.0" encoding="utf-8"?>
<WMS>
<Order>
<Header>
<RARefNum>RASO000001</RARefNum>
<WMSCategory>ESSVMI</WMSCategory>
<CustomerID>nVidia</CustomerID>
<CreationDate>2013-12-02 06:29:50</CreationDate>
<OrderDate>2013-12-02 06:29:50</OrderDate>
<ExpectedShippedDate>2013-12-02 06:29:50</ExpectedShippedDate>
<LastShippedDate>2013-12-02 06:29:50</LastShippedDate>
<CustomerOrderReference>nVidia9338</CustomerOrderReference>
<CustomerShipmentNo>81475721</CustomerShipmentNo>
<CustomerSONo>SO982733</CustomerSONo>
<CustomerInvoiceNo>INV987373</CustomerInvoiceNo>
<CustomerReference1>nVidia 1</CustomerReference1>
<CustomerReference2/>
<WMSReference1>Emp 1</WMSReference1>
<WMSReference2>Emp 2</WMSReference2>
<ShipmentNo>IWU997872</ShipmentNo>
<DocumentNo>KK98764394</DocumentNo>
<Transportation>
<Mode>Freight</Mode>
<VehicleType/>
</Transportation>
<Carrier>
<ID>Fedex</ID>
<Name>Fedex SG</Name>
<Address>Changi Singapore</Address>
<Country/>
<PostalCode/>
<Contact>
<Sequence/>
<Person/>
<Email/>
<DID/>
<Handphone/>
</Contact>
</Carrier>
<Consignee>
<ID>ABC</ID>
<Name>ABC Corp</Name>
<Address>Jurong West, Singapore</Address>
<Country/>
<PostalCode/>
<Contact>
<Sequence/>
<Person/>
<Email/>
<DID/>
<Handphone/>
</Contact>
</Consignee>
<Containers/>
</Header>
<Details>
<Detail>
<LineNo>1</LineNo>
<SKU>SKU0001</SKU>
<SKUDescription>SKU 0001</SKUDescription>
<Package>50</Package>
<OrderedQty>600.000</OrderedQty>
<PickedQty>600.000</PickedQty>
<PickedDate>2013-12-02 06:35:09</PickedDate>
<ShippedQty>600.000</ShippedQty>
<ShippedDate>2013-12-02 06:35:09</ShippedDate>
<ManufactoryDate>2013-12-02 06:35:09</ManufactoryDate>
<ExpiryDate>2014-12-02 06:35:09</ExpiryDate>
<FIFODate>2013-06-02 06:35:09</FIFODate>
<CustomerLotRef1>nVidia 2093</CustomerLotRef1>
<CustomerLotRef2>nVidia 2099</CustomerLotRef2>
<LineReference1>10</LineReference1>
</Detail>
<Detail>
<LineNo>2</LineNo>
<SKU>SKU0002</SKU>
<SKUDescription>SKU 0002</SKUDescription>
<Package>50</Package>
<OrderedQty>100.000</OrderedQty>
<PickedQty>100.000</PickedQty>
<PickedDate>2013-12-02 06:35:09</PickedDate>
<ShippedQty>100.000</ShippedQty>
<ShippedDate>2013-12-02 06:35:09</ShippedDate>
<ManufactoryDate>2013-12-02 06:35:09</ManufactoryDate>
<ExpiryDate>2014-12-02 06:35:09</ExpiryDate>
<FIFODate>2013-06-02 06:35:09</FIFODate>
<CustomerLotRef1>nVidia 2193</CustomerLotRef1>
<CustomerLotRef2>nVidia 2199</CustomerLotRef2>
<LineReference1>10</LineReference1>
</Detail>
</Details>
</Order>
</WMS>
Is there a better way to code it?
In sql server support lot of xml format outputs.
This query returns a xml document from two tables. Maybe you are using
linq, then after completing your sql query, you execute the query from
linq.
select table1.column1, table2.column2 from table1 inner join table2 on table2.table1_id = table1.Id for xml auto
Check this link.
I dont know if this is better but I would probably make some variables instead of calling the linq in the xml. Then you can just call the variable in the xml document.
Something like this maybe:
private static void CreateDatabaseXml(string path)
{
tbchrDataContext db = new tbchrDataContext();
var rARefNum = db.T_ORDER_DETAILs.Select(i => i.RARefNum).Single();
var customer = db.T_ORDER_HEADERs.Select(i => i.Customer).Single();
var supplierName = db.T_ORDER_DETAILs.Select(i => i.SupplierName).Single();
XDocument doc = new XDocument(
// XML Declaration
new XDeclaration("1.0", "utf-8", "yes"),
// XML Root element to 3rd in nest
new XElement(ns + "WMS",
new XElement(ns + "Order",
new XElement(ns + "Header", new XElement(ns + "RARefNum", rARefNum),
new XElement (ns + "WMSCategory", customer),
new XElement (ns + "CustomerID", supplierName)))) );
#endregion
doc.Save(path);
}
I have the following code:
XNamespace testNM = "urn:lst-emp:emp";
XDocument xDoc;
string path = "project_data.xml";
if (!File.Exists(path))
{
xDoc = new XDocument(
new XDeclaration("1.0", "UTF-16", null),
new XElement(testNM + "Test")
);
}
else
{
xDoc = XDocument.Load(path);
}
var element = new XElement("key",
new XElement("Type", type),
new XElement("Value", value));
xDoc.Element(testNM + "Test").Add(element);
// Save to Disk
xDoc.Save(path);
which produces an output in the XML file like this:
<?xml version="1.0" encoding="utf-16"?>
<Test xmlns="urn:lst-emp:emp">
<key xmlns="">
<Type>String</Type>
<Value>somestring</Value>
</key>
</Test>
How can I get an output like this in the XML file instead?
<?xml version="1.0" encoding="utf-16"?>
<Tests xmlns="urn:lst-emp:emp">
<key name="someString">
<Type>String</Type>
<Value>somestring</Value>
</key >
</Tests>
Note its only the 3rd line that has changed in the XML file.
You can do it this way:
var element = new XElement("key",
new XAttribute("name", "someString"),
new XElement("Type", "type"),
new XElement("Value", "value"));
To provide a complete version of Bilyukov's answer, this should produce the output expected. Obviously substitute the "someString" static string with a variable populated as you wish. Changes include using XName.Get(string, string) to create the appropriate XName objects for the XElement constructors.
XNamespace testNM = "urn:lst-emp:emp";
XDocument xDoc;
string path = "project_data.xml";
if (!File.Exists(path))
{
xDoc = new XDocument(
new XDeclaration("1.0", "UTF-16", null),
new XElement(XName.Get("Tests", testNM.NamespaceName))
);
}
else
{
xDoc = XDocument.Load(path);
}
var element = new XElement(XName.Get("key", testNM.NamespaceName),
new XAttribute("name", "someString"),
new XElement("Type", type),
new XElement("Value", value));
xDoc.Element(XName.Get("Tests", testNM.NamespaceName)).Add(element);
// Save to Disk
xDoc.Save(path);
Your XML has default namespace. Descendants of the element where default namespace declared is considered in the same default namespace, unless it is explicitly declared with different namespace. That's why you need to use the same XNamespace for <key> element. :
var element = new XElement(testNM +"key",
new XAttribute("name", "someString"),
new XElement(testNM +"Type", type),
new XElement(testNM +"Value", value));
I have a xml file like this:
<Tests>
<Test>
<Name>Test1</Name>
<Type>A</Type>
</Test>
<Test>
<Name>Test2</Name>
<Type>A</Type>
</Test>
<Test>
<Name>Test3</Name>
<Type>B</Type>
</Test>
</Tests>
How can I return a string array or list which only contains name of the Test which theire type is A?
I am trying with this code but no success!
XPathNodeIterator it = nav.Select("/Tests/Test[Type = 'A']/Name)
Don't you want to try linq2xml?
using System.Xml.Linq;
using System.Linq;
///////////
XElement root = new XElement("Tests",
new XElement("Test",
new XElement("Name", "Test1"),
new XElement("Type", "A")),
new XElement("Test",
new XElement("Name", "Test2"),
new XElement("Type", "A")),
new XElement("Test",
new XElement("Name", "Test3"),
new XElement("Type", "B")));
string[] result = (from xe in root.Elements()
where xe.Element("Type").Value.Equals("A")
select xe.Element("Name").Value).ToArray();
The XPath expression in your question matches Name elements. If you want to match Test elements instead, you have to remove the /Name part:
XPathNodeIterator it = nav.Select("/Tests/Test[Type = 'A']);
If you want to use an XPathNavigator, from there, you can call MoveToChild() to point the navigator to the Name elements:
foreach (XPathNavigator elemNav in it) {
elemNav.MoveToChild("Name", "");
string name = elemNav.Value;
// Do something with 'name'...
}
I have some XML
<Users>
<User Name="Z"/>
<User Name="D"/>
<User Name="A"/>
</User>
I want to sort that by Name. I load that xml using XDocument. How can I view that xml sorted by Name?
You can sort using LINQ to Xml, if XmlDocument is not the case
XDocument input = XDocument.Load(#"input.xml");
XDocument output = new XDocument(
new XElement("Users",
from node in input.Root.Elements()
orderby node.Attribute("Name").Value descending
select node));
XDocument xdoc = new XDocument(
new XElement("Users",
new XElement("Name", "Z"),
new XElement("Name", "D"),
new XElement("Name", "A")));
var doc = xdoc.Element("Users").Elements("Name").OrderBy(n => n.Value);
XDocument doc2 = new XDocument(new XElement("Users", doc));