C# Append Xmlnode into document but it removes the exisitng xmlNode - c#

I have an XMLdocument which has 5 number of envelopes Nodes. I have to clone the envelope based on index number what I am passing to the method. Basically the envelopes are appending at the end of XML after appending but it removes the envelopes node from the xmldocument and save. For example if I pass index as two, the method will clone the XMLnode from xmldocument but while cloning/copying it removes the nodes from the current document. what is wrong in my code.
public void findScenarioSeqAndClone(int sequence)
{
XmlDocument doc = new XmlDocument();
//XmlDocument newdoc = new XmlDocument();
doc = xml_doc.getXMLdoc();
XmlNodeList envelops = doc.GetElementsByTagName("envelope");
if (sequence == -1)
{
sequence = 0;
}
int count = 0;
foreach (XmlNode envelop in envelops)
{
if (sequence == count)
{
XmlNode node = envelop.SelectSingleNode("//requestid");
node.InnerText = node.InnerText + 1;
XmlNode refElem = doc.DocumentElement.LastChild;
doc.DocumentElement.InsertAfter(newNode, refElem);
break;
}
count = count + 1;
}
doc.Save(#"\\abs3006\POC\ASP\Document_NB115_updates.xml");
}
XML file will be like this
<?xml version="1.0" encoding="windows-1252" standalone="yes"?>
<file>
<envelope>
<document_request>
<document_info>
<requestid>00000111</requestid>
...information tags
</document_info>
<inserts>
<groupid>1</groupid>
</inserts>
<grouping>
---
</grouping>
</envelope>
<envelope>
<document_request>
<document_info>
<requestid>00000222</requestid>
...information tags
</document_info>
<inserts>
<groupid>1</groupid>
</inserts>
<grouping>
---
</grouping>
</envelope>
The result I m getting as below if I pass sequence as "1". My code should find the first envelop and append to the XML document. But its not working.
<?xml version="1.0" encoding="windows-1252" standalone="yes"?>
<file>
<envelope>
<document_request>
<document_info>
<requestid>00000222</requestid>
...information tags
</document_info>
<inserts>
<groupid>1</groupid>
</inserts>
<grouping>
---
</grouping>
</envelope>
<envelope>
<document_request>
<document_info>
<requestid>00000111</requestid>
...information tags
</document_info>
<inserts>
<groupid>1</groupid>
</inserts>
<grouping>
---
</grouping>
</envelope>
My expected result would be as below when I pass sequence 1.
<?xml version="1.0" encoding="windows-1252" standalone="yes"?>
<file>
<envelope>
<document_request>
<document_info>
<requestid>00000111</requestid>
...information tags
</document_info>
<inserts>
<groupid>1</groupid>
</inserts>
<grouping>
---
</grouping>
</envelope>
<envelope>
<document_request>
<document_info>
<requestid>00000222</requestid>
...information tags
</document_info>
<inserts>
<groupid>1</groupid>
</inserts>
<grouping>
---
</grouping>
</envelope>
<envelope>
<document_request>
<document_info>
<requestid>00000111</requestid>
...information tags
</document_info>
<inserts>
<groupid>1</groupid>
</inserts>
<grouping>
---
</grouping>
</envelope>
Any Help would be highly appreciated.

Related

How to move up the XML `Element` one step higher and change its `XName` to this format `parent_child` using `Linq to XML` in C#

I am trying to modify the following XML doc (MRE) using Linq to XML:
Move the school name and address one step higher or at the level of its parent—school element.
At the same time, change its name to <School_Name> and <School_Address>.
ORIGINAL
<?xml version="1.0" encoding="utf-8"?>
<GreatGrandParent>
<GrandParent>
<Parent>
<Child>
<Name>John</Name>
<Address>California</Address>
<Sex>Male</Sex>
<Age>18</Age>
<School>
<Name>Cool School</Name>
<Address>California</Address>
</School>
</Child>
<Child>
<Name>Mary</Name>
<Address>New Orleans</Address>
<Sex>Female</Sex>
<Age>16</Age>
<School>
<Name>Pretty School</Name>
<Address>New Orleans</Address>
</School>
</Child>
<Parent>
<GrandParent>
<GreatGrandParent>
TARGET MODIFICATION
<?xml version="1.0" encoding="utf-8"?>
<GreatGrandParent>
<GrandParent>
<Parent>
<Child>
<Name>John</Name>
<Address>California</Address>
<Sex>Male/Sex>
<Age>18</Age>
<School_Name>Cool School</School_Name>
<School_Address>California</School_Address>
</Child>
<Child>
<Name>Mary</Name>
<Address>New Orleans</Address>
<Sex>Female/Sex>
<Age>16</Age>
<School_Name>Pretty School</School_Name>
<School_Address>New Orleans</School_Address>
</Child>
<Parent>
<GrandParent>
<GreatGrandParent>
HERE'S WHAT I HAVE DONE SO FAR:
XDocument doc = XDocument.Load(#"D:\Xml\Childs Profile.xml");
XElement root = doc.XPathSelectElement("//Parent");
IEnumerable<XElement> rootlists = root.Descendants("Child").ToList();
foreach (var rootlist in rootlists)
{
XElement lists = root.Element("Child");
XElement name = root.Element("Child").Element("School").Element("Name");
XElement address = root.Element("Child").Element("School").Element("Address");
list.AddFirst(name);
list.AddFirst(address);
XElement school = root.Element("Child").Element("School");
school.Remove();
}
doc.Save(#"D:\Xml\Childs Profile.xml");
ISSUES: The foreach above does not move to next child.
PENDING: Change the XName to <School_Name> and <School_Address> either before or after moving.
You can try this:
XDocument doc = XDocument.Load(#"the.xml");
var child = doc.Descendants("Child");
var school = child.Elements("School");
string name = $"{school.First().Name}_{school.Elements("Name").First().Name}";
string address = $"{school.First().Name}_{school.Elements("Address").First().Name}";
foreach (var s in school)
{
s.Parent.Add(new XElement(name, s.Element("Name").Value));
s.Parent.Add(new XElement(address, s.Element("Address").Value));
}
school.Remove();
doc.Save(#"out.xml");

C# XML File: How to select a node with a certain value using LINQ

I am having difficulties figuring out the Linq way to extract the value of the specific node.
Lets say my XML file is this:
<?xml version="1.0" encoding="utf-8"?>
<Data>
<Month>
<Month_Number>1</Month_Number>
<Tool>
<Tool_Name>Help</Tool_Name>
<Count>1</Count>
</Tool>
</Month>
<Month>
<Month_Number>2</Month_Number>
<Tool>
<Tool_Name>On</Tool_Name>
<Count>1</Count>
</Tool>
</Month>
<Month>
<Month_Number>3</Month_Number>
<Tool>
<Tool_Name>Off</Tool_Name>
<Count>1</Count>
</Tool>
</Month>
</Data>
I would like to extract value fromCount which is from Tool with Tool_Name with value of Off in Month where Month_Number is 3.
The answer should be 1. Then I would like to change that value to 2
So resulting XML file would be
<?xml version="1.0" encoding="utf-8"?>
<Data>
<Month>
<Month_Number>1</Month_Number>
<Tool>
<Tool_Name>Help</Tool_Name>
<Count>1</Count>
</Tool>
</Month>
<Month>
<Month_Number>2</Month_Number>
<Tool>
<Tool_Name>On</Tool_Name>
<Count>1</Count>
</Tool>
</Month>
<Month>
<Month_Number>3</Month_Number>
<Tool>
<Tool_Name>Off</Tool_Name>
<Count>2</Count>
</Tool>
</Month>
</Data>
using XMLDocument I would do something similar to
XmlDocument tallyFile = new XmlDocument();
tallyFile.Load(tallyFilePath);
XmlNode node = tallyFile["Data"];
foreach (XmlNode childNode in node.ChildNodes)
{
if (childNode["Month_Number"].InnerText.Equals("3")){}
}
But I would like to achieve the above using XDocument
Can you try this code, just reference the docs
using System.Xml.Linq;
XElement root = XElement.Load(tallyFilePath);
foreach (var month in root.Descendants("Month")
.Where(x => x.Descendants("Month_Number").First().Value == "3"))
{
Console.WriteLine(month);
//month.Value = "2";
}

RemoveChild when node is empty

I want to remove some child elements from an XML structure using RemoveChild() if a node is empty. My XML:
<Customers>
<customer>
<Name>John</Name>
<Age>25</Age>
<Status></Status>
</Customer>
<customer>
<Name>John</Name>
<Age></Age>
<Status></Status>
</Customer>
</Customers>
Should become:
<Customers>
<customer>
<Name>John</Name>
<Age>25</Age>
</Customer>
<customer>
<Name>John</Name>
</Customer>
</Customers>
My code so far:
XmlElement element3 = xmlDocument.CreateElement("Age");
element3.InnerText = str3;
element1.AppendChild((XmlNode)element3);
XmlElement element4 = xmlDocument.CreateElement("Status");
element4.InnerText = str4;
element1.AppendChild((XmlNode)element4);
How can I remove the empty node resp. nodes if there is more than one empty node?
Add a condition to only create the element if you need to:
if (!string.IsNullOrEmpty(status))
{
XmlElement statusElement = xmlDocument.CreateElement("Status");
statusElement.InnerText = status;
customerElement.AppendChild((XmlNode)statusElement);
}
Or if you need to remove it after it's already created (e.g. because you get XML from an external source with an empty Status), use the same sort of condition to remove it:
if (!string.IsNullOrEmpty(status))
{
customerElement.RemoveChild(statusElement);
}
That is because you are trying to remove a child element that simply does not exist. You must understand that in this context, the RemoveChild() method expects a reference to an existing node within the parent's children.
If i were to use your code sample above and create a standalone representation of this, it would look like this:
XmlDocument doc = new XmlDocument();
XmlElement element1 = doc.CreateElement("Customer");
XmlElement element2 = doc.CreateElement("Name");
element2.InnerText = "John";
element1.AppendChild(element2);
XmlElement element3 = doc.CreateElement("Age");
element3.InnerText = "25";
element1.AppendChild(element3);
XmlElement element4 = doc.CreateElement("Status");
element4.InnerText="";
element1.AppendChild(element4);
doc.AppendChild(element1);
element1.RemoveChild(element1.SelectSingleNode("Status"));
Using Linq-to-XML:
If you want nodes like:
<a>
<b>
<c></c>
</b>
</a>
to become:
<a />
Use:
XElement root = XElement.Load(file);
root.Descendants().Reverse().ToList().ForEach(x =>
{
if (x.IsEmpty)
x.Remove();
});
But if you want it to be:
<a>
<b />
</a>
Remove the .Reverse()

Replacing Some Elements in XML [Sample XML Provided]

I have an xml document that looks like this.I have a XML file structured as below.
Sample XML is as follows:
<Dr.Watson>
<Bugs>
<Bug Name="Bug.add --> AAAAAAAAAAAA">
<criteria>
<includeFilterSets>
<filterSet>
<filter>
<filterName>PRODUCT_NAME</filterName>
<operator>
<name>Equals</name>
</operator>
<value>Dr.Watson</value>
</filter>
</filterSet>
</includeFilterSets>
<grouping>
<groupBy>
<name>STATUS</name>
</groupBy>
</grouping>
<caseSensitive>false</caseSensitive>
<entityToSearch>
<name>BUG</name>
</entityToSearch>
</criteria>
</Bug>
</Bugs>
</Dr.Watson>
I want to replace some of elements in the XML file like below:
<Dr.Watson>
<Bugs>
<Bug Name="Bug.add --> AAAAAAAAAAAA">
<criteria>
<includeFilterSets>
<filterSet>
<filter>
<filterName>PRODUCT_NAME</filterName>
<operator>
<name>Equals</name>
</operator>
<value>Dr.Watson</value>
</filter>
</filterSet>
</includeFilterSets>
<grouping>
<groupBy>
<name>STATE</name>
</groupBy>
</grouping>
<caseSensitive>false</caseSensitive>
<entityToSearch>
<name>BUG</name>
</entityToSearch>
</criteria>
</Bug>
</Bugs>
</Dr.Watson>
i would like to change the available under followed by as State.
Please suggest.
var xdoc = XDocument.Load(path_to_xml);
var groupByName = xdoc.XPathSelectElement("//groupBy/name");
groupByName.Value = "STATE";
xdoc.Save(path_to_xml);

How to extract a part of xml code from an xml file using c# code

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<eRecon xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:noNamespaceSchemaLocation="eRecon.xsd">
<Header>
<Company Code="" />
<CommonCarrierCode />
<InputFileName InputIDPk="">F:\ReconNew\TmesysRec20100111.rec</InputFileName>
<BatchNumber>000152</BatchNumber>
<InputStartDateTime>2010-02-26 11:47:00</InputStartDateTime>
<InputFinishDateTime>2010-02-26 11:47:05</InputFinishDateTime>
<RecordCount>8</RecordCount>
</Header>
<Detail>
<CarrierStatusDate>2010-01-11</CarrierStatusDate>
<ClaimNum>YDF02892 C</ClaimNum>
<InvoiceNum>0108013775</InvoiceNum>
<LineItemNum>001</LineItemNum>
<NABP>10600211</NABP>
<RxNumber>4695045</RxNumber>
<RxDate>2008-07-21</RxDate>
<CheckNum />
<PaymentStatus>PENDING</PaymentStatus>
<RejectDescription />
<InvoiceChargeAmount>152.15</InvoiceChargeAmount>
<InvoicePaidAmount>131.00</InvoicePaidAmount>
</Detail>
</eRecon>
How can I extract the portion
<Header>
<Company Code="" />
<CommonCarrierCode />
<InputFileName InputIDPk="">F:\ReconNew\TmesysRec20100111.rec</InputFileName>
<BatchNumber>000152</BatchNumber>
<InputStartDateTime>2010-02-26 11:47:00</InputStartDateTime>
<InputFinishDateTime>2010-02-26 11:47:05</InputFinishDateTime>
<RecordCount>8</RecordCount>
</Header>
from the above xml file.
I need the c# code to extract a part of xml tag from an xml file.
If the file isn't too big (smaller than a few MB), you can load it into an XmlDocument:
XmlDocument doc = new XmlDocument();
doc.Load(#"C:\yourfile.xml");
and then you can parse for the <Header> element using an XPath expression:
XmlNode headerNode = doc.SelectSingleNode("/eRecon/Header");
if(headerNode != null)
{
string headerNodeXml = headerNode.OuterXml;
}
You can use XPath like in this tutorial:
http://www.codeproject.com/KB/cpp/myXPath.aspx
Use Linq-to-xml:
XDocument xmlDoc = XDocument.Load(#"c:\sample.xml");
var header = xmlDoc.Descendants("Header").FirstOrDefault();
Linq version
string fileName=#"d:\xml.xml";
var descendants = from i in XDocument.Load(fileName).Descendants("Header")
select i;

Categories

Resources