Read an XML document and removing nodes - c#

I have an XML file, similar to the one below. I will read the XML and find the EmpId node. Based on other data will determine if I need to keep this node or delete the node. Currently have a process which reads it and creates a list of Record Ids which I will need to remove. In the below XML I will want to keep the EmpId = Emp1 and remove EmpId = Emp2. The removal is the node.
I believe the best approach is to read the XML first to determine which nodes to keep and then go thru the XML again and remove the necessary nodes.
What's the best approach to remove these nodes?
I'm open to creating a new XML document and creating the node which need to be kept. Based on the data I'm reading it's 50/50 if I'll be removing more nodes or keeping more nodes.
...
<HeaderNode>
<Details>
<SubmissionId>1</SubmissionId>
<EmpDetail>
<RecordId>1</RecordId>
<EmpDempgraphic>
<EmpId>Emp1</EmpId>
</EmpDempgraphic>
</EmpDetail>
<EmpDetail>
<RecordId>2</RecordId>
<EmpDempgraphic>
<EmpId>Emp2</EmpId>
</EmpDempgraphic>
</EmpDetail>
</Details>
</HeaderNode>
...

Using Xml Linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace XML
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement EmpDetail = doc.Descendants("EmpDetail").Where(x => (int)x.Element("RecordId") == 2).FirstOrDefault();
EmpDetail.Remove();
}
}
}

Unless the document is huge, just load it into an XDocument, Remove the elements you don't want, and Save the document back out.

Related

Replacing XML innerText with XMLElement or XElement

//I would like to get some advice on how to replace the node value of a element in XML using XMLElement or XElement. Right now I'm trying it with XMLElement but the compiler gives me only errors or the XML replace the whole document insted of selected node. I have a XML/XSD sample that I need to fill with data and create like 500 XML a day but I cant insert the data into the right elements.
I expect that I can replace / insert data into the element value. Like I want to change the City text value. I have a table with content and based on the filled data I need to add it into specific XML elements and save.
As for now every sample code I found and some I covered up did give compile errors / null reference object( at assigning InnerText) or deleted all the elements and added just one line with my text value.
Te code below gives me ''Object reference not set to an instance of an object.'
' at .InnerText. Actually the declatarion of SelectSingleNode("ID") return me also a null.
-<Receiver>
-<ID>
<RNumber>9999999999</RNumber>
<Name>ABC AGD sp. z o. o.</Name>
</ID>
-<Address>
-<AddressSpec>
<Country>PL</Country>
<Street>Kwiatowa</Street>
<HouseNum>1</HouseNum>
<City>Warszawa</City>
</AddressSpec>
</Address>
<Email>test#test.pl</Email>
<Phone>667444555</Phone>
</ID>
-</Receiver>
using System.IO;
using System.Net;
using System.Xml;
using System.Xml.Linq;
class ReplaceXMLData
{
public static void Main(Args _args)
{
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.Load(//path/sample.xml);
System.Xml.XmlElement root = doc.DocumentElement;
System.Xml.XmlElement Street = doc.SelectSingleNode("Street");
Street.innertext = "random";
doc.AppendChild(root);
doc.Save(path);
info("Details added Successfully");
}}
Here is solution using Xml Linq (XDocument). You need to use Decendants with FirstOrDefault
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication15
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement id = doc.Descendants("ID").FirstOrDefault();
}
}
}

Parsing XML file C#

I can't parse the attribute value from this file, I used Linq and the standard library. Object reference error. Need attribut's value "RequeryNumber".
XML file
Excel Query:
exctract = XML.DocumentElement
.SelectSingleNode("//KPOKS/ReestrExtract/DeclarAttribute")
.Attributes
.getNamedItem("RequeryNumber").Text
SelectSingleNode() uses XPath to find XML nodes that fulfill the filter.
There are several ways to get what you want. If RequeryNumber only exists on one node, you could do like this:
var attribute = xDoc.DocumentElement
.SelectSingleNode("//*[#RequeryNumber]/#RequeryNumber");
MessageBox.Show("text" + attribute.InnerText);
[#RequeryNumber] finds the node which has an attribute named "RequeryNumber".
/#RequeryNumber extracts that specific attribute, on which you can get the value using the InnerText property.
I would suggest you take a look at: XPath cheatsheet
I had one error on following line in the xml that I fixed
I parsed below your xml and needed to add the namespace to get the XElement using Xml Linq.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XNamespace ns = doc.Root.GetDefaultNamespace();
XElement declarAttribute = doc.Descendants(ns + "DeclarAttribute").FirstOrDefault();
}
}
}

Iteration on XML tags in C#

How would code an iteration to loop through the parent tag on a xml file as below:
<collection>
<parent>
<child1>DHL</child1>
<child2>9000000131</child2>
<child3>ISS Gjøvik</child13>
<child4>ISS Gjøvik</child4>
<child5>ISS Gjøvik</child5>
<child6>9999000000136</child6>
</parent>
<parent>
<child1>DHL</child1>
<child2>9000000132</child2>
<child3>ISS Gjøvik</child13>
<child4>ISS Gjøvik</child4>
<child5>ISS Gjøvik</child5>
<child6>9999000000136</child6>
</parent>
<parent>
<child1>DHL</child1>
<child2>9000000134</child2>
<child3>ISS Gjøvik</child13>
<child4>ISS Gjøvik</child4>
<child5>ISS Gjøvik</child5>
<child6>9999000000136</child6>
</parent>
</collection>
I need to insert the value of child1 as the primary key into the DB.
Have you tried the XmlReader? What do you have so far? Please show us some code. Just a reminder, StackOverflow is a helpdesk, not a programming service.
I see DHL in one of the tags. If that refers to the postal delivery company, they have an API (SDK) that is easy to use from within .NET code..
If you want to use XML (de)serialization that I would suggest that you start reading the System.Xml.Serialization namespace documentation. Microsoft has provided more than enough documentation and examples.
Link to namespace docs: https://msdn.microsoft.com/en-us/library/system.xml.serialization(v=vs.110).aspx
Here are some examples that contains anything that you would need to deserialzation the xml document to a poco class:
https://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx
Assuming your xml is in the string variable xml:
var xdoc = XDocument.Parse(xml);
foreach (var parentEls in xdoc.Root.Elements("parent"))
{
string child1Value = parentEls.Element("child1").Value;
// your logic using child1 value
}
Note that your xml is malformed - <child3> is closed by </child13>.
Using xml linq to parse everything
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("parent").Select(x => new {
child1 = (string)x.Element("child1"),
child2 = (string)x.Element("child2"),
child3 = (string)x.Element("child3"),
child4 = (string)x.Element("child4"),
child5 = (string)x.Element("child5"),
child6 = (string)x.Element("child6")
}).ToList();
}
}
}

C# XML program to append inner block of newXElement

I have a C# program which appends a specific inner block of XML element to an existing XML file (the XML document has 457 lines), the data is coming from a hard coded xls spreadsheet. I’m using LINQ to XML with xml.Descendants(), and AddBeforeSelf() method. The program works fine only if I have two records to append, and when I upload 3 records or more than two, the new XML Element are not inserted on the right section, the 3rd and succeeding records are appending on the wrong block of inner Element.
The goal of my program is to get the records from xls spreadsheet with multiple records and insert them to specific inner XML node. For example, xml element of OrderLine is currently on line 110, the program should insert the new block before line 110, it works when I only have two records, but it won’t work when I have more than two records.
Please see my XML Grid view, notice that there are 2 records under ReleaseLine, as well as under ShipUnit. The succeeding record must be inserted to the right node, or it must be nested under ReleaseLine and ShipUnit. I appreciate your help, thanks!
XML Grid View
Here is my code sample:
public class EditOrder
XElement xml = XElement.Load(#"C:\OrderTest.xml");
var childrens = xml.Descendants().ToArray();
var next_releaseline = childrens[110];
var next_shipunit = childrens[110];
Console.WriteLine(childrens[0]); //prints out the whole content
next_orderline.AddBeforeSelf(new XElement("ReleaseLine",
new XElement("ReleaseLineGid",
new XElement("PackagedItemRef",
new XElement("ItemQuantity",)
newXelement(Test),
....)));
next_shipunit.AddBeforeSelf(new XElement("ShipUnit",
new XElement("ShipUnit",
new XElement("WeightVolume",
new XElement("ShipUnitContent",))));
xml.Save(#"C:\OrderTest.xml");
And I'm calling the EditOrder class from another class to execute the program.
//Call from another class to execute the XML insertion
ProjectXML2.EditOrder.Main();
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication61
{
class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<Transmission>" +
"<TransmissionBody>" +
"<Release>" +
"<ShiptoLocation></ShiptoLocation>" +
"<TimeFrame></TimeFrame>" +
"</Release>" +
"</TransmissionBody>" +
"</Transmission>";
XDocument doc = XDocument.Parse(xml);
XElement releaseLine = new XElement("ReleaseLine",
new XElement("ReleaseLineGid",
new XElement("PackagedItemRef",
new XElement("ItemQuantity"))));
XElement shipUnit = new XElement("ShipUnit",
new XElement("ShipUnit",
new XElement("WeightVolume",
new XElement("ShipUnitContent"))));
XElement release = doc.Descendants("Release").FirstOrDefault();
release.Add(releaseLine);
release.Add(shipUnit);
}
}
}

Adding ANY user input as a node in an XML document

I want to add an XML string as new node to an existing XML document.
For example, suppose the input from the user is:
<bk:book>
<title>Pride And Prejudice</title>
<authorlastname>Jane</authorlastname>
<authorfirstname>Austen</authorfirstname>
<price>24.95</price>
</bk:book>
I am trying to insert that user input as follows:
xml_SourceDoc.Root.LastNode.AddAfterSelf(XElement.Parse(xmlString));
However, that statement is raising this exception:
bk is an undeclared prefix. Line 1, position 2.
How can I change my approach so that I can successfully insert any text that is input by the user?
If you really don't know what the user will enter, you can simply handle it as CDATA via the LINQ to XML XCData Class.
Here is what your sample data would look like when inserted as a node in a container XML document:
<doc>
<content><![CDATA[<bk:book>
<title>Pride And Prejudice</title>
<authorlastname>Jane</authorlastname>
<authorfirstname>Austen</authorfirstname>
<price>24.95</price>
</bk:book>]]></content>
</doc>
And here is an example program that creates the above example document:
using System;
using System.Xml;
using System.Xml.Linq;
public class CDataExample
{
public static void Main()
{
string documentXml = "<doc><content></content></doc>";
XElement doc = XElement.Parse(documentXml, LoadOptions.None);
string userInput =
#"<bk:book>
<title>Pride And Prejudice</title>
<authorlastname>Jane</authorlastname>
<authorfirstname>Austen</authorfirstname>
<price>24.95</price>
</bk:book>";
XCData cdata = new XCData(userInput);
doc.Element("content").Add(cdata);
Console.WriteLine(doc.ToString());
}
}
Check the xml is parsable first:
Check well-formed XML without a try/catch?
if(IsValidXML(xmlString))
{
xml_SourceDoc.Root.LastNode.AddAfterSelf(XElement.Parse(xmlString));
}
first, create XElement you want to add:
xmlString = new XElement(new XElement("book", new XAttribute("bk) ,(new XElement("title",
titleValue), new EXelement("authorlastname", authorlastNameValue ...
and so on.
then add it:
xml_SourceDoc.Root.Add(xmlString);
exception you mention is caused that you do not add attribute creating XElement

Categories