Modify xml, child nodes with same name - c#

I am trying to modify a xmlString so i can create a dataset on the fly.
The xml looks like this:
<?xml version="1.0"?>
<ds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ttActivity>
<a-actno>1030371</a-actno>
<a-status>Start</a-status>
<a-solution/>
<a-descript>hei</a-descript>
<a-descript>hopp</a-descript>
<a-acttypegr>0</a-acttypegr>
<a-calltype/>
</ttActivity>
</ds>
The problem when creating a dataset using dataset.ReadXML(xmlReader) is the 2 nodes with same name "a-descript". Is there a quick way to fix this xml so that the nodes get unique names. ie: a-descript1 and a-descript2 ??

using LINQ to XML
XDocument doc = XDocument.Parse(xmlString);
doc.Descendants("a-descript").Last().Name = "a-descript2";
xmlString = doc.ToString();

Related

How to get the name of elements/attributes in xml files and write these into another new xml file using LINQ

I am new to c#. Right now I am trying to get the name of some specific elements in an xml file and create a new xml file for these.
I have tried with LINQ, so that I can parse the xml and get the name of some elments that I want.
I do not want to use console.writeline to output this name. Instead I would like to create a new xml file and save these names in it.
Can anyone give me some tips?
The following is example data I would like to parse:
<root>
<Package>
<Class name="EnterpriseArchitect">
<Operation/>
</Class>
<Class name="ZachmanFramework">
<Operation/>
</Class>
</Package>
</root>
I want to get the attribute name of the element Class and save it in a new xml file like this:
<root>
<EnterpriseArchitect/>
<ZachmanFramework/>
</root>
The following is my c# code, but I can not reach the goal:
XDocument xdoc = XDocument.Load(#"C:\Users\jsc\Desktop\123456.xml");
XDocument xNew = new XDocument();
var datatype = xdoc.Root.Elements("Package").Elements("Class")
foreach (var dut in datatype)
{
var dataTypeName = dut.Attribute("name").Value;
xNew.Add(new XElement(dataTypeName));
}
xNew.Save(#"C:\Users\jsc\Desktop\1234567.xml");
Please, read my comments to the question.
This should work:
XDocument srcdoc = XDocument.Load("sourceFileName.xml");
List<XElement> names = srcdoc.Descendants("Class")
.Select(x=> new XElement(x.Attribute("name").Value))
//.Distinct() //uncomment this if duplicate values aren't allowed
.ToList();
XDocument newdoc = new XDocument();
XElement root = new XElement("root");
root.Add(names);
newdoc.Add(root);
newdoc.Save("newFileName.xml");
Good luck!

Append New Element in XML VB or C#

I apologize if this question is too easy for you as I am just starting to learn how XML works. What I am trying to do is to append a new element to App/Library and for example I started with this.
<?xml version="1.0" encoding="utf-8"?>
<App>
<Library>
<Count>100</Count>
<Track>
<TrackID>1</TrackID>
<Name>New York</Name>
<Artist>Snow Patrol</Name>
</Track>
</Library>
</App>
what I am trying to do is to add another track to my existing XML.
<Track>
<TrackID>2</TrackID>
<Name>Chasing Cars</Name>
<Artist>Snow Patrol</Name>
</Track>
There are a couple of ways to deal with xml manipulation in .NET. The older style using System.Xml.XmlDocument or using System.Xml.Linq.XDocument approach.
Here is an example on how to do it using XmlDocument:
var xml = "Baz";
var doc = new XmlDocument();
doc.LoadXml(xml); //Load up the original xml string into XmlDocument object
var fooNode = doc.SelectSingleNode("//foo"); //use xpath to get to the top level foo element
var newBar = doc.CreateElement("bar"); //Create a new bar element and assign it's inner text
newBar.InnerText = "Baz2";
fooNode.AppendChild(newBar); //append the newly created bar element to foo
and here is an example on how to do it using XDocument (which is much more simpler):
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><foo><bar>Baz</bar></foo>";
var xdoc = XDocument.Parse(xml); //Load up the original xml string into Linq XDocument object
xdoc.Root.Add(new XElement("bar", "Bar2")); //Add <bar>Bar2</bar> to foo (which is root of the document)
Here is a running example:
https://dotnetfiddle.net/vY7Vag

xml Nodes by Element

Below is an example of the xml file that I need to pull data via C#. This is my first experience with reading xml files and a beginner with xml. Anyone have an example of how I would find/load the fieldorder values for Export_B?
<?xml version="1.0" encoding="utf-8"?>
<Config>
<OutFolderCSV>c:\Output\2012\upload_Files</OutFolderCSV>
<OutFolderImage>c:\Output\2012\NM_Scorecard_Images</OutFolderImage>
<PathOutLogFile>c:\Output\2012\Log\Matches.log</PathOutLogFile>
<FieldSeparator>,</FieldSeparator>
<ExportFile>
<Name>Export_A</Name>
<FieldOrder>matchID</FieldOrder>
<FieldOrder>contactID</FieldOrder>
<FieldOrder>stageID13</FieldOrder>
<FieldOrder>stringScore1a</FieldOrder>
<FieldOrder>xScore1a</FieldOrder>
<FieldOrder>stageID14</FieldOrder>
<FieldOrder>stringScore1b</FieldOrder>
<FieldOrder>xScore1b</FieldOrder>
<FieldOrder>stageID15</FieldOrder>
<FieldOrder>stringScore1c</FieldOrder>
<FieldOrder>xScore1c</FieldOrder>
</ExportFile>
<ExportFile>
<Name>Export_B</Name>
<FieldOrder>matchID</FieldOrder>
<FieldOrder>contactID</FieldOrder>
<FieldOrder>stageID16</FieldOrder>
<FieldOrder>stringScore1a</FieldOrder>
<FieldOrder>xScore1a</FieldOrder>
<FieldOrder>stageID17</FieldOrder>
<FieldOrder>stringScore1b</FieldOrder>
<FieldOrder>xScore1b</FieldOrder>
<FieldOrder>stageID18</FieldOrder>
<FieldOrder>stringScore1c</FieldOrder>
<FieldOrder>xScore</FieldOrder>
</ExportFile>
</Config>
Using LINQ to XML:
var doc = XDocument.Load(#"c:\path\to\file.xml");
var fieldOrders =
from exportFile in doc.Descendants("ExportFile")
where (string)exportFile.Element("Name") == "Export_B"
from fieldOrder in exportFile.Elements("FieldOrder")
select (string)fieldOrder;
I have written an article
http://www.codeproject.com/Articles/33769/Basics-of-LINQ-Lamda-Expressions
on XML using XDocument object.
You can parse the XML easily using
XDocument.Load(filepath)
Please read the section XLinq to parse the objects.
edit :
You can change value of Export_B using the code :
var document = XDocument.Load(filepath)
var exportFiles = document.Descandants("ExportFile");
List<XElement> list = new List<XElement>();
foreach(var element in exportFiles)
{
list.Add(element);
// Now you can do element.Element("Name") to get the name. Put a breakpoint on this, you can get the reference of all underlying objects.
}

Reading XML using C# is this the proper approach?

I have a project where i read XML that was exported from another system. The XML looks like this:
<?xml version="1.0" encoding="ISO-8859-1"?><xmlimexport>
<companydata/>
<articles/>
<customers/>
<suppliers/>
<orders>
<order>
<atOrder>
<OOI_HEAD_DOCUMENT_NUMBER>12345</OOI_HEAD_DOCUMENT_NUMBER>
**... more rows ...**
</atOrder>
<rows>
<row><OOI_ROW_ARTICLE_NUMBER>12345</OOI_ROW_ARTICLE_NUMBER><OOI_ROW_ARTICLE_TEXT>SuperDuperArticleName</OOI_ROW_TEXT>**... more data...**</row>
</rows>
</order>
</orders>
<bests/>
<invoices/>
<supplierinvoices/>
<pricelists/>
<parcels/>
</xmlimexport>
So what i do is load the path to the XML file then:
XmlDocument doc = new XmlDocument();
// Load xml file
doc.Load(xmlFile);
// Read order data
XmlNodeList orderList = doc.GetElementsByTagName("order");
foreach (XmlElement order in orderList)
{
try
{
// Read atOrder data (single node)
XmlNode atOrder = order.SelectSingleNode("atOrder");
// Read article data (one or many nodes)
XmlNodeList articles = order.GetElementsByTagName("row");
// Create a order
Order customerOrder = new Order();
Then read data with:
customerOrder.CUS_ID = Convert.ToInt32(atOrder.SelectSingleNode("OOI_HEAD_DOCUMENT_NUMBER").InnerText);
But since it can be both Strings, Booleans, Datetime, Date and INT in those fields i find myself having to use Convert. very much, is this the proper way to do this or should i use a different approach?
you can also generate an XSD and based on an XSD a class to deserialize the XML (short tutorial here)
you can read the XML directly into a DataSet (.ReadXML)
Have a look at LinqToXml I think that might help:
http://msdn.microsoft.com/en-us/library/bb387098.aspx

I am trying to read directory from xml file in c# and have problem

<?xml version="1.0" encoding="UTF-8"?>
<form:Documents xmlns:form="http://www.abbyy.com/FlexiCapture/Schemas/Export/FormData.xsd" xmlns:addData="http://www.abbyy.com/FlexiCapture/Schemas/Export/AdditionalFormData.xsd">
<_Document_Definition_1:_Document_Definition_1 addData:ImagePath="C:\POC\Export\Test.pdf" xmlns:_Document_Definition_1="http://www.abbyy.com/FlexiCapture/Schemas/Export/Document_Definition_1.xsd">
<_Page_1>
<_First_Name>John</_First_Name>
<_Last_Name>Doe</_Last_Name>
</_Page_1>
</_Document_Definition_1:_Document_Definition_1>
</form:Documents>
I have xml containing directory of pdf file which I would need to read.
I can read first name and last name from _Page_1 node but do not know how to read ImagePath.
Here is my code to read from _Page_1
XDocument xDoc = XDocument.Load("Test.xml");
var poc = from p in xDoc.Descendants("_Page_1")
select new
{
FirstName = p.Element("_First_Name").Value,
LastNumber = p.Element("_Last_Name").Value
};
// Execute the query
foreach (var customer in poc)
{
Console.WriteLine(customer.FirstName);
Console.WriteLine(customer.LastName);
}
//Pause the application
Console.ReadLine();
Thank you BrokenGlass, it's working.
I have one more question.
What if I have several iteration of _Document_Definition node, how do I read each iteration.
<?xml version="1.0" encoding="UTF-8"?>
<form:Documents xmlns:form="http://www.abbyy.com/FlexiCapture/Schemas/Export/FormData.xsd" xmlns:addData="http://www.abbyy.com/FlexiCapture/Schemas/Export/AdditionalFormData.xsd">
<_Document_Definition_1:_Document_Definition_1 addData:ImagePath="C:\POC\Export\Test.pdf" xmlns:_Document_Definition_1="http://www.abbyy.com/FlexiCapture/Schemas/Export/Document_Definition_1.xsd">
<_Page_1>
<_First_Name>John</_First_Name>
<_Last_Name>Doe</_Last_Name>
</_Page_1>
</_Document_Definition_1:_Document_Definition_1>
<_Document_Definition_1:_Document_Definition_1 addData:ImagePath="C:\POC\Export\Test2.pdf" xmlns:_Document_Definition_1="http://www.abbyy.com/FlexiCapture/Schemas/Export/Document_Definition_1.xsd">
<_Page_1>
<_First_Name>Jane</_First_Name>
<_Last_Name>Doe</_Last_Name>
</_Page_1>
</_Document_Definition_1:_Document_Definition_1>
</form:Documents>
You are missing the XML namespace references to access those attributes, this works:
XDocument doc = XDocument.Load(#"test.xml");
XNamespace _Document_Definition_1 = "http://www.abbyy.com/FlexiCapture/Schemas/Export/Document_Definition_1.xsd";
XNamespace addData = "http://www.abbyy.com/FlexiCapture/Schemas/Export/AdditionalFormData.xsd";
string impagePath = doc.Descendants(_Document_Definition_1 + "_Document_Definition_1")
.First()
.Attribute(addData + "ImagePath")
.Value;
It looks like Imagepath is an attribute not an element. Hence you are not able to read it. Check for the attributes in the xml file.

Categories