Issue with reading nodes and its elements using XDocument in C# - c#

I have an xml document like as shown below.
<?xml version="1.0" encoding="UTF-8"?>
<Projects>
<Project>
<ProjectNo>111</ProjectNo>
<Client/>
<Responsible/>
<Participants/>
<Date>13-11-2015</Date>
</Project>
<Transfers ID="1">
<SampleID>1</SampleID>
<SampleNo>222</SampleNo>
<ChamberNo>p111</ChamberNo>
</Transfers>
<Transfers ID="2">
<SampleID>2</SampleID>
<SampleNo>32</SampleNo>
<ChamberNo>p311</ChamberNo>
</Transfers>
<Transfers ID="3">
<SampleID>3</SampleID>
<SampleNo>42</SampleNo>
<ChamberNo>p211</ChamberNo>
</Transfers>
</Projects>
I am trying to read nodes and its elements like this
XDocument xmlDocument = XDocument.Load(GlobalVariables.XmlPath + "\\" + GlobalVariables.ProjectID + ".xml");
var project = from p in xmlDocument.Descendants("Project")
select new Project
{
ProjectNo = p.Element("ProjectNo").Value,
Client = p.Element("Client").Value,
ProjectResponsible = p.Element("Responsible").Value,
Participants = p.Element("Participants").Value,
Date = Convert.ToDateTime(p.Element("Date").Value).Date,
};
var Samples = (from s in xmlDocument.Descendants("Transfers")
select new Sample
{
SampleID = Convert.ToInt32(s.Element("SampleID").Value),
SampleNo = s.Element("SampleNo").Value,
ChamberNo = s.Element("ChamberNo").Value,
}
);
int SamplesNo = Samples.Count();
CreateWordDocument(project, Samples, SamplesNo);
I am able to read nodes and its elements at first time but if i edit values in xml file and try to read again then i am getting error "NullreferenceException was unhandled" Object reference not set to an instance of an object.
What might be the problem and how to rectify it?
Any suggestions?

Related

C# XML - Deserializing a list of classes

I'm working with an XML document which is generated using C# from a list of objects (of the 'People' class)
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfDeviceInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="DeviceInfoCollection">
<DeviceInfo>
<Partition>0</Partition>
<SerialID>3117132000001</SerialID>
<AzureID>2d680cd1-7320-43a9-87d4-75a2698771a3</AzureID>
<FirmwareVersion>3.0.0</FirmwareVersion>
</DeviceInfo>
<DeviceInfo>
<Partition>0</Partition>
<SerialID>3117132000002</SerialID>
<AzureID>646ca461-9352-4746-9fa6-6308010059fb</AzureID>
<FirmwareVersion>1.1.2</FirmwareVersion>
</DeviceInfo>
My goal is to deserialize this back into a List<DeviceInfo> variable.
I've tried the following
var xDoc = XDocument.Load(Application.StartupPath + "/devicesTEST.xml");
if (File.ReadAllText(Application.StartupPath + "/devicesTEST.xml").Length > 0)
{
var envs = from e in xDoc.Root.Descendants("DeviceInfo")
select new DeviceInfo
{
SerialID = (string)e.Element("SerialID"),
};
Manager.Devices = envs.ToList();
}
and it's working for me on another XML file.
Update
Contrary to previous belief, it turns out there is no error, the list just doesn't get populated with the values extracted from the XML.
XML namespaces; in your xml, the namespace is defined by xmlns="DeviceInfoCollection" - but your code assumes it is the empty (default) namespace. Since xml namespaces are inherited, you need to tell it the namespace throughout:
XNamespace ns = "DeviceInfoCollection";
var devices = from e in xDoc.Root.Descendants(ns + "DeviceInfo")
select new DeviceInfo
{
SerialID = (string)e.Element(ns + "SerialID"),
};
foreach(var device in devices)
{
Console.WriteLine(device.SerialID);
}

Xml delete node by elements value

Here is xml file:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Data>
<PageInfo>
<ID>0</ID>
<NUM>5</NUM>
<URL>er.php</URL>
</PageInfo>
<PageInfo>
<ID>1</ID>
<NUM> 12345</NUM>
<URL>/out/out.ViewFolder.php</URL>
</PageInfo>
</Data>
I have tried alot of ways (for a week now) to delete certain node (PageInfo) by element (ID,NUM,URL) in this xml file.
There are few approaches I have tried:
1st approach:
XmlDocument docc = new XmlDocument();
docc.LoadXml(AppDomain.CurrentDomain.BaseDirectory + "/WebData.xml");
XmlNode nodee = docc.SelectSingleNode("/Data/PageInfo/ID[2]");
nodee.RemoveAll();
2nd approach:
XmlDocument document = new XmlDocument();
document.Load(AppDomain.CurrentDomain.BaseDirectory + "/WebData.xml");
XmlNodeList nodes = document.DocumentElement.SelectNodes("/Data/PageInfo");
string ID, NUM, URL;
foreach (XmlNode node in nodes)
{
ID = node.SelectSingleNode("ID").InnerText;
NUM = node.SelectSingleNode("NUM").InnerText;
URL = node.SelectSingleNode("URL").InnerText;
node.RemoveAll();
Console.WriteLine(ID + " " + NUM + " " + URL + "\n");
}
1st solution does not trigger and exception but nothing happens, 2nd solution throws an exception: Data at the root level is invalid.
How one would be able to delete nodes by elements value in an xml file? (LINQ is fine)
Disclaimer: all solutions I have found on StackOverflow does not work for my certain case.
Based on the ID, please try this solution :
First approach
string xml = AppDomain.CurrentDomain.BaseDirectory + "/WebData.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xml);
XmlNode t = xmlDoc.SelectSingleNode("/Data/PageInfo[ID='0']");
t.ParentNode.RemoveChild(t);
xmlDoc.Save(xml);
Second approach : Linq
XDocument xmlDoc = XDocument.Load(xml);
var pageInfo = (from xml2 in xmlDoc.Descendants("PageInfo")
where xml2.Element("ID").Value == "0"
|| xml2.Element("NUM").Value == "5"
|| xml2.Element("URL").Value == "er.php"
select xml2).FirstOrDefault();
pageInfo.Remove();
xmlDoc.Save(xml);
// output
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Data>
<PageInfo>
<ID>1</ID>
<NUM> 12345</NUM>
<URL>/out/out.ViewFolder.php</URL>
</PageInfo>
</Data>
As <Data> is an array so you can deserialize it in a classData which has List<PageInfo> so you can update your data accordingly and then serialize it back in your file.
Example:
XmlArray("Data")]
public class Data
{
[XmlArrayItem("PageInfo")]
public List<PageInfo> pageInfos = new List<PageInfo>();
}
public class PageInfo
{
public int ID;
public int NUM;
public string URL;
}
Now you can apply queries on your list and then deserialize your Data class back to file. See This Link for Serializing guide.

How to read single node value from xml file

Hi i am trying to get value from xml but it shows node null.
Here is my xml file.
<?xml version="1.0" encoding="utf-8"?>
<result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://www.cfhdocmail.com/TestAPI2/Result.xsd https://www.cfhdocmail.com/TestAPI2/Result.xsd" xmlns="https://www.cfhdocmail.com/TestAPI2/Result.xsd">
<data>
<key>MailingGUID</key>
<value>0aa2b2e3-7afa-4002-ab2f-9eb4cbe33ae7</value>
</data>
<data>
<key>OrderRef</key>
<value>52186</value>
</data>
</result>
I want to get "MailingGUID" value.
Here is the code that i have tried:
private void readXML()
{
XmlDocument xml = new XmlDocument();
// You'll need to put the correct path to your xml file here
xml.Load(Server.MapPath("~/XmlFile11.xml"));
// Select a specific node
XmlNode node = xml.SelectSingleNode("result/data/value");
// Get its value
string name = node.InnerText;
}
Please tell me how i can get MailingGUID value.
Thanks
UPDATE:
I think there might be something wrong with your schemas, I removed references to them and your code worked fine. I tried this:
const string str = "<?xml version=\"1.0\" encoding=\"utf-8\"?><result><data><key>MailingGUID</key><value>0aa2b2e3-7afa-4002-ab2f-9eb4cbe33ae7</value></data><data><key>OrderRef</key><value>52186</value></data></result>";
var xml = new XmlDocument();
xml.LoadXml(str);
xml.DocumentElement.SelectSingleNode("/result/data/value").InnerText
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//Parsing of xml is done here
Document doc = builder.parse(new File("C:\\Users\\User_Name\\Documents\\My Received Files\\PDSL_ABM.xml"));
//Here we get the root element of XML and print out
doc.getDocumentElement().normalize();
System.out.println ("Root element of the doc is " + doc.getDocumentElement().getNodeName());
NodeList list = doc.getElementsByTagName("MailingGUID");
int totalMailingGUID =list.getLength();
System.out.println("Total no of MailingGUID : " + totalSupplierPartID);
//Traversing all the elements from the list and printing out its data
for (int i = 0; i < list.getLength(); i++) {
//Getting one node from the list.
Node childNode = list.item(i);
System.out.println("MailingGUID : " + childNode.getTextContent());
}

Insert new child node in an existing XML

Good day everyone. I would like to ask for help with my code. I have here an XML document containing the following.
<?xml version="1.0" encoding="utf-8" ?>
<TechnicalReport>
<Data quantity = "2" description ="myDesc" findings = "none" actiontaken = "none" />
</TechnicalReport>
What I would like to do here is to add another child node inside the . I have searched for so many websites about my problem but to no avail. For example, I will add another node, say:
<?xml version="1.0" encoding="utf-8" ?>
<TechnicalReport>
<Data quantity = "2" description ="myDesc" findings = "none" actiontaken = "none" />
<Data quantity = "3" description ="myDesc2" findings = "none2" actiontaken = "none3" />
</TechnicalReport>
I have successfully compiled and loaded the XML file into a Repeater control using an XMLDataSource, but when I do an insert from my form, the Repeater control does not update its contents, and even my XML file also does not update.
Here's my C# code:
public void AddNewRecord()
{
//Load XML Schema
XmlDocument originalXml = new XmlDocument();
originalXml.Load(Server.MapPath("xmlTechReportDetails.xml"));
//Create the node name Technical Report
XmlNode TechReport = originalXml.SelectSingleNode("TechnicalReport");
XmlNode Data = originalXml.CreateNode(XmlNodeType.Element, "Data", null);
//Insert quantity
XmlAttribute quantity = originalXml.CreateAttribute("quantity");
quantity.Value = txtQty.Text;
//Insert description
XmlAttribute description = originalXml.CreateAttribute("description");
description.Value = txtDescription.Text;
//Insert findings
XmlAttribute findings = originalXml.CreateAttribute("findings");
findings.Value = txtFindings.Text;
//Insert actions taken.
XmlAttribute actionTaken = originalXml.CreateAttribute("actiontaken");
actionTaken.Value = txtAction.Text;
Data.Attributes.Append(quantity);
Data.Attributes.Append(description);
Data.Attributes.Append(findings);
Data.Attributes.Append(actionTaken);
TechReport.AppendChild(Data);
}
Please help.
Try adding this at the end of your method:
originalXml.Save(Server.MapPath("xmlTechReportDetails.xml"));
I think it's because you did not save the file. That's why your changes are not retained.
Instead of this code:
//Create the node name Technical Report
XmlNode TechReport = originalXml.SelectSingleNode("TechnicalReport");
Use this code
XmlNodeList nodeList = originalXml.GetElementsByTagName("connectionStrings");

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