How to read xml in c# with XElement? - c#

I have this xml
<Folder.FolderStructure
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/FileSiteAPI.Models">
<a_attr i:nil="true" />
<checkedout>false</checkedout>
<children>
<Folder.FolderStructure>
<checkedout>false</checkedout>
<children />
<created>2018-11-29T13:58:57</created>
<edited>2018-11-29T13:58:57</edited>
<extension>MSG</extension>
<id>36878331</id>
<rootfolder>false</rootfolder>
<searchfolder>false</searchfolder>
<size>29696</size>
<state i:nil="true" />
<version>1</version>
</Folder.FolderStructure>
<Folder.FolderStructure>
<checkedout>false</checkedout>
<children />
<created>2019-01-15T10:18:03</created>
<edited>2019-01-15T10:18:03</edited>
<extension>DOCX</extension>
<id>37584622</id>
<rootfolder>false</rootfolder>
<searchfolder>false</searchfolder>
<size>42345</size>
<state i:nil="true" />
<version>1</version>
</Folder.FolderStructure>
<Folder.FolderStructure>
<a_attr i:nil="true" />
<checkedout>false</checkedout>
<children i:nil="true" />
<created>0001-01-01T00:00:00</created>
<edited>0001-01-01T00:00:00</edited>
<extension i:nil="true" />
<id>2478514</id>
<rootfolder>false</rootfolder>
<searchfolder>false</searchfolder>
<size>0</size>
<state i:nil="true" />
<version>0</version>
</Folder.FolderStructure>
</children>
<created>0001-01-01T00:00:00</created>
<edited>0001-01-01T00:00:00</edited>
<extension i:nil="true" />
<id>2469288</id>
<rootfolder>false</rootfolder>
<searchfolder>false</searchfolder>
<size>72041</size>
<state i:nil="true" />
<text>Public</text>
<version>0</version>
</Folder.FolderStructure>
but when I parse it and try to read the 3 Folder.FolderStructure elements, it comes back with empty set.
XElement folder_xml = XElement.Parse(xml_str);
List<XElement> elements = folder_xml.Elements("Folder.FolderStructure").ToList();
Console.WriteLine(elements.Count);
Anyone know what's wrong?

You need to define the namespace and use Descendants instead of Elements:
XElement folder_xml = XElement.Parse(xml_str);
XNamespace ns = "http://schemas.datacontract.org/2004/07/FileSiteAPI.Models";
var elements = folder_xml.Descendants(ns + "Folder.FolderStructure").ToList();
Console.WriteLine(elements.Count);

Related

Delete data in XML with C#

I have the following XML File:
<order id="1234">
<users>
<user id="102030" nick="nickname" done="false" />
<user id="123456" nick="nickname" done="false" />
</users>
<machines>
<machine id="123" sd="123" ref="" done="false" />
<machine id="456" sd="456" ref="" done="false" />
<machine id="789" sd="789" ref="" done="false" />
</machines>
</order>
I want to delete the user with the id 102030, so the xml looks like this:
<users>
<user id="123456" nick="nickname" done="false" />
</users>
<machines>
<machine id="123" sd="123" ref="" done="false" />
<machine id="456" sd="456" ref="" done="false" />
<machine id="789" sd="789" ref="" done="false" />
</machines>
</order>
This is my code which doesn't work:
XmlDocument doc = XmlDocument.Load(path);
XmlNodeList nodes = doc.GetElementsByTagName("users");
foreach(XmlNode node in nodes){
foreach(XmlAttribute attribute in node.Attributes){
if(attribute.Name== "id" && attribute.Value == "102030"){
node.RemoveAll();
}
}
}
doc.Save(path);
I am a newbie in C# so I need every help!
Thanks in advance, geibi
XmlNode.RemoveAll() does not remove a node. Instead it:
Removes all the child nodes and/or attributes of the current node.
Thus, instead you need to remove the node from its parent:
node.ParentNode.RemoveChild(node);

c# - Adding new parent node to existing Xml File

I have the following xml file and want to add a new parent node after the last existing node.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<testsuite id="" name="Test Projekt test">
<node_order />
<details />
<testsuite id="" name="Test Suite 1">
<node_order />
<details />
<testsuite id="" name="Test Suite Operation 2">
<node_order />
<details />
</testsuite>
</testsuite>
</testsuite>
<new node here>
i tryed to use the following code but it didnĀ“t worked
XmlElement testsuite = doc_save.CreateElement("testsuite");
XmlAttribute ID = doc_save.CreateAttribute("id");
XmlAttribute Name = doc_save.CreateAttribute("name");
XmlElement node_order = doc_save.CreateElement("node_order");
XmlElement details = doc_save.CreateElement("details");
doc_save.DocumentElement.AppendChild(testsuite);
testsuite.Attributes.Append(ID);
testsuite.Attributes.Append(Name);
testsuite.AppendChild(node_order);
testsuite.AppendChild(details);
How can I do this?
Expanding on the comment by #hotfix, rename your root element and when I ran your code it was working for me. See the XML and code I was using below.
XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<testsuites id="" name="Test Projekt test">
<node_order />
<details />
<testsuite id="" name="Test Suite 1">
<node_order />
<details />
<testsuite id="" name="Test Suite Operation 2">
<node_order />
<details />
</testsuite>
</testsuite>
<testsuite id="" name="">
<node_order />
<details />
</testsuite>
</testsuites>
Code:
XmlDocument document = new XmlDocument();
document.Load(#"your\xml\file");
XmlElement testsuite = document.CreateElement("testsuite");
XmlAttribute ID = document.CreateAttribute("id");
XmlAttribute Name = document.CreateAttribute("name");
XmlElement node_order = document.CreateElement("node_order");
XmlElement details = document.CreateElement("details");
document.DocumentElement.AppendChild(testsuite);
testsuite.Attributes.Append(ID);
testsuite.Attributes.Append(Name);
testsuite.AppendChild(node_order);
testsuite.AppendChild(details);
document.Save(#"your\xml\file");

Swapping nodes in xmlNodeList C#

Assuming having the following xml
<test>
<step>
<var name="name1" />
<var name="name2" />
</step>
<step>
<var name="name3" />
<var name="name4" />
</step>
<step>
<var name="name5" />
<var name="name6" />
</step>
</test>
I m using XmlNodeList, seperated by "step". Is there a way to swap or replace a step directly in the xmlnodelist?
Need to make it like this:
<test>
<step>
<var name="name3" />
<var name="name4" />
</step>
<step>
<var name="name1" />
<var name="name2" />
</step>
<step>
<var name="name5" />
<var name="name6" />
</step>
</test>
You can use XDocument class instead of XMLDocument. This will swap the var nodes name3 with name6.
using System.Linq;
using System.Xml.Linq;
class Test
{
static void Main()
{
XDocument document = XDocument.Load("test.xml");
Swap("name3", "name6", document);
document.Save("test.xml");
}
static void Swap(string nameOne, string nameTwo, XDocument document)
{
var nameOneNode = document.Descendants("var").FirstOrDefault(p => p.Attribute("name").Value == nameOne);
var nameTwoNode = document.Descendants("var").FirstOrDefault(p => p.Attribute("name").Value == nameTwo);
nameOneNode.Attribute("name").Value = nameTwo;
nameTwoNode.Attribute("name").Value = nameOne;
}
}
The order of the nodes in an XML file does not necessarily have to be kept when the XML file is read. For example, if your file looks like this:
<xmlcontent>
<node value="Hello" />
<node value="World" />
</xmlcontent>
The XML read may return the nodes like this:
<xmlcontent>
<node value="World" />
<node value="Hello" />
</xmlcontent>
To apply something like an "order" to XML nodes, you need to add an attribute you can sort by, like
<xmlcontent>
<node index="1" value="Hello" />
<node index="2" value="World" />
</xmlcontent>
In that case, "swapping" two elements would come down to swapping the index values.
Finally managed to do it, here is the code:
XmlDocument xml;
XmlNodeList xmlList;
xml = new XmlDocument();
xml.Load(path);
xmlList = xml.GetElementsByTagName("step");
XmlNode refNode = xmlList[1];
XmlNode newNode = xmlList[0];
xml.DocumentElement.InsertAfter(newNode, refNode);

XML extracting attributes using XMLDocument

i am trying to parse an xml element using XMLDocument (DItem >> Title)
below is my code but somehow i am not getting hold of it.... any help?
XmlDocument xmldoc = new XmlDocument();
XmlNamespaceManager xmlns = new XmlNamespaceManager(xdoc.NameTable);
xmlns.AddNamespace("DItems", "http://namespace.xsd");
xmldoc.Load(url);
var title = xmldoc.SelectNodes("content", xmlns);
foreach (XmlNode node in title)
{
string title = node.Attributes["Title"].Value;
//this.ddlTitle.Items.Add(new ListItem(title));
}
here is my XML:
<?xml version='1.0'?>
<root xmlns="http://www.w3.org/2005/Atom">
<title type="text">title</title>
<entry>
<content type="application/xml">
<Items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.namespace.xsd">
<CatalogSource Acronym="ABC" OrganizationName="organization name" />
<Item Id="28466" CatalogUrl="url">
<DItem xmlns:content="http://namespace.xsd" TargetUrl="http://index.html" Title="my title1">
<content:Source Acronym="ABC" OrganizationName="ABC" />
</DItem>
</Item>
</Items>
</content>
</entry>
<entry>
<content type="application/xml">
<Items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.namespace.xsd">
<CatalogSource Acronym="ABC" OrganizationName="organization name" />
<Item Id="28466" CatalogUrl="url">
<DItem xmlns:content="http://namespace.xsd" TargetUrl="http://index.html" Title="my title2">
<content:Source Acronym="ABC" OrganizationName="ABC" />
</DItem>
</Item>
</Items>
</content>
</entry>
<entry>
<content type="application/xml">
<Items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.namespace.xsd">
<CatalogSource Acronym="ABC" OrganizationName="organization name" />
<Item Id="28466" CatalogUrl="url">
<DItem xmlns:content="http://namespace.xsd" TargetUrl="http://index.html" Title="my title3">
<content:Source Acronym="ABC" OrganizationName="ABC" />
</DItem>
</Item>
</Items>
</content>
</entry>
</root>
var xmldoc = new XmlDocument();
var xmlns = new XmlNamespaceManager(xmldoc.NameTable);
xmlns.AddNamespace("DItems", "http://www.namespace.xsd");
xmldoc.Load(url);
var titleNodes = xmldoc.SelectNodes("//DItems:DItem/#Title", xmlns);
var result = titleNodes.Cast<XmlAttribute>().Select(a => a.Value).ToList();
Output (list of objects):
my title1
my title2
my title3

Xml file reading using XML to LINQ in C#

I've an xml file (Sample.xml) which has the following structure
<RootElement>
<Children>
<Child Name="FirstChild" Start="0" End="2">
<Sibling Name="Test1" />
<Sibling Name="Test2" />
<AdditionalSibling Name="Add_Test_1" />
<AdditionalSibling Name="Add_Test_2" />
<MissingSibling Name="Miss_Test_1" />
<MissingSibling Name="Miss_Test_2" /
</Child>
<Child Name="SecondChild" Start="0" End="2">
<Sibling Name="Test3" />
<Sibling Name="Test4" />
</Child>
<Child Name="ThirdChild" Start="0" End="2">
<Sibling Name="Test5" />
<Sibling Name="Test6" />
</Child>
<Child Name="FourthChild" Start="0" End="2">
<Sibling Name="Test7" />
<Sibling Name="Test8" />
</Child>
<Child Name="FifthChild" Start="0" End="2">
<Sibling Name="Test9" />
<Sibling Name="Test10" />
</Child>
<Child Name="SixthChild" Start="0" End="2">
<Sibling Name="Test11" />
<Sibling Name="Test12" />
</Child>
<MatchedChilds>
<Child Name="FirstChild" />
<Child Name="SecondChild" />
<Child Name="ThirdChild" />
<Child Name="FourthChild" />
<Child Name="FifthChild" />
<Child Name="SixthChild" />
</MatchedChilds>
</Children>
</RootElement>
i need to read the attribute values of the element" Child" which is directly under "RootElement"
Now i'm using the LINQ query like
List<string> lst = (from element in XDocument.Load(Application.StartupPath + "\\Sample.xml")
.Descendants("Child")
group element by element.Attribute("Name").Value into KeyGroup select KeyGroup.Key )
.ToList();
but it returns the attribute value of "Name" of all the "Child" element in the file.
Please give me a better solution to do this using XML to LINQ
Thanks in advance
Use something like this:
XDocument doc = XDocument.Load(Application.StartupPath + "\\Sample.xml");
List<string> lst = doc.Root.Elements("Child")
.Select(x => (string) x.Attribute("Name"))
.ToList();
Note the use of Elements() instead of Descendants(). That will get you all the name attributes. It's unclear to me why you were grouping in your original sample code, but hopefully this will get you going.
You grouped by name, so your list would have name elements. You may query and iterate your results as follows:
var query = from element in XDocument.Load(Application.StartupPath + "\\Sample.xml")
.Descendants("Child")
group element by element.Attribute("Name").Value into KeyGroup
select new { Grouping = KeyGroup.Key, Children = KeyGroup };
and the iteration
foreach(var namekey in query)
{
Console.WriteLine(namekey.Grouping);
foreach(var child in namekey.Children)
{
Console.WriteLine(child.whatever);
}
}

Categories