Linq to Xml - Get a valid xml document after remove operation - c#

For a xml Document like below I display all subfolders and files for the currently selected folder. For that from the xml string i remove the unmatched folders and built a UI using XSLT on the front end. Seems the operation is removing all the nodes that makes resulting string invalid xml. so
How do i remove elements from xml using Linq to Xml without changing the validity of the document
Xml Document
<?xml version="1.0" encoding="utf-8"?>
<Folder>
<Folders>
<Folder ID="1" Name="Root" ParentId="0">
<Files></Files>
</Folder>
<Folder ID="2" Name="My Documents" ParentId="1">
<Files>
<File Name="LicenceCode.txt" Size="2000" CreatedOn="1/1/2012 12:12:00 PM" CreatedBy="1" ModifiedOn="1/10/2012 10:12:56 AM" ModifiedBy="2"></File>
</Files>
</Folder>
</Folders>
</Folder>
Code
XElement filesAndFolders = XElement.Parse(xmlDocumentString);
string outputFolders = string.concat(from folders in filesAndFolders in filesAndFolder.Elements("Folder").Folder("Folders") where folders.Attribute("ParentId").Value.Equals(selectedFolderId) select folders);
//pass outputFolders string to xsl to build the UI
Problem
The outputFolders string is invalid as it contains only below string not a valid document
<Folder ID="2" Name="My Documents" ParentId="1">
<Files>
<File Name="LicenceCode.txt" Size="2000" CreatedOn="1/1/2012 12:12:00 PM" CreatedBy="1" ModifiedOn="1/10/2012 10:12:56 AM" ModifiedBy="2"></File>
</Files>
</Folder>

How about removing the elements you don't want:
var doc = XDocument.Parse(xmlString);
doc.Element("Folder").Element("Folders").Elements("Folder").Where(f => f.Attribute("ID").Value == "1").Remove();

Related

Iterating through linq results results in more items than query count

I'm fairly new to LINQ but this seemed pretty straightforward.
I have an XML doc which contains a structure like this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<folders>
<folder id="-1" parent="-100">
<name><![CDATA[Root]]></name>
<children>
<folder id="2" parent="-1">
<name><![CDATA[Contribution]]></name>
<documents />
<children>
<folder id="775" parent="2">
<name><![CDATA[category1]]></name>
<documents />
<children>
<folder id="2319" parent="775">
<name><![CDATA[Acad_Depts1]]></name>
<documents />
<children>
<folder id="26965" parent="2319">
<name><![CDATA[Student1]]></name>
<documents>
<document>
</document>
</documents>
</folder
</children>
</folder>
<folder id="2319" parent="775">
<name><![CDATA[Acad_Depts2]]></name>
<documents />
<children>
<folder id="26965" parent="2319">
<name><![CDATA[Student1]]></name>
<documents>
<document>
</document>
</documents>
</folder
</children>
</folder>
etc...
</children>
</folder>
</children>
</folder>
</children>
</folder>
</folders>
What I'm trying to do is to select all the elements with an attribute 'parent="775"'.
XElement xelement = XElement.Load("folders_only_registrar_folder.xml");
IEnumerable <XElement> folders = xelement.Elements();
var query = from node in folders.Descendants("folder")
where node.Attribute("parent").Value == registrarNodeID
select node;
Console.WriteLine(query.Count());
Console.ReadKey();
foreach(XElement departmentNode in query.Descendants("name"))
{
Console.WriteLine(departmentNode.Value.ToString());
}
When I run the query and test the count, I get 48 results (which is good)... but when I try to write out those same nodes, I get hundreds of results. For some reason it's giving me almost ALL of the elements named "folder" including children folders.
Thoughts as to what I'm doing wrong?
UPDATE... ok so now I know why i'm getting all the folders but any thoughts on how to create a collection of each grouping of nodes and sub-nodes?
Can the selection in LINQ send each 775 folder node (plus it's collective sub-nodes) into some sort of collection of nodes and then I could parse through them in a foreach by grouping of node?
Replace query.Descendants() with just query. query.Descendants() gets every child of every node that was originally contained within query.

How to use LINQ to get data from an XML file?

I have xml files which look like this:
<?xml version="1.0" encoding="utf-8"?>
<record id="177" restricted="false">
<type>record type</type>
<startdate>2000-10-10</startdate>
<enddate>2014-02-01</enddate>
<titles>
<title xml:lang="en" type="main">Main title</title>
<!-- only one title element with type main -->
<title xml:lang="de" type="official">German title</title>
<!-- can have more titles of type official -->
</titles>
<description>description of the record</description>
<categories>
<category id="122">
<name>category name</name>
<description>category description</description>
</category>
<!-- can have more categories -->
</categories>
<tags>
<tag id="5434">
<name>tag name</name>
<description>tag description</description>
</tag>
<!-- can have more tags -->
</tags>
</record>
How do I select the data from these xml files using LINQ, or should I use something else?
You can load xml into XDocument objects using either the Load() method
for files, or the Parse() method for strings:
var doc = XDocument.Load("your-file.xml");
// OR
var doc = XDocument.Parse(yourXmlString);
Then you can access the data using LINQ:
var titles =
from title in doc.XPathSelectElements("//title")
where title.Attribute("type").Value == "official"
select title.Value;
Was searching for examples of Xmlserializer and found this: How to Deserialize XML document
So why not to try. I did Ctrl+C and Edit -> Paste Special -> Paste XML As Classes in Visual Studio 2013 and... Whoa I got all the classes generated. One condition target framework must be 4.5 and this function is available from Visual Studio 2012+ (as stated in that post)

Extracting App version number from XML with C#

I have an XML file as follows. I would like to extract the Version number from this file.
I tried XML parsing. But, that is for node values only. I am able to get this file as string as follows. var doc = XDocument.Load("WMAppManifest.xml");
<?xml version="1.0" encoding="utf-8"?>
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2012/deployment" AppPlatformVersion="8.0">
<DefaultLanguage xmlns="" code="en-US" />
<App xmlns="" ProductID="{a3f55b1e-c183-4645-9b19-87a41a206978}" Title="sometitle" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal" Author="M-Files author" BitsPerPixel="32" Description="Apache Cordova for Windows Phone" Publisher="CordovaExample" PublisherID="{b93a0d8e-5aa9-4d9b-b232-17e2d852e779}">
<IconPath IsRelative="true" IsResource="false">ApplicationIcon.png</IconPath>
</App>
</Deployment>
You can access the XML declaration node as follows:
XmlDeclaration declaration = doc.ChildNodes
.OfType<XmlDeclaration>()
.FirstOrDefault();
You can then read the value of declaration.Version.
Or, if you are after the 'app' version attribute in the XML document itself, try the following
string version = doc.Descendants("App")
.Single()
.Attribute("Version").Value

Finding the difference between two XML files

I have built two XML files that map the content of a given folder:
<root>
<folder name="C:\a\b" permision="yes" folderCount="1">
<folders>
<folder name="C:\a\b\c" permision="yes" folderCount="1">
<folders>
<folder name="C:\a\b\c\e" permision="yes" folderCount="0">
<folders/>
<files>
<file name="401-1.htm"/>
<file name="401-2.htm"/>
<file name="401-3.htm"/>
</files>
</folder>
<folder name="C:\a\b\d" permision="yes" folderCount="0">
<folders/>
<files>
<file name="401-4.htm"/>
<file name="401-5.htm"/>
<file name="401-3.htm"/>
</files>
</folder>
</folders>
<files/>
</folder>
</root>
I'd like to know if there is a way to find the difference between the files.
(One file is the old state and the second is the new state, and it's only possible to add files and not remove them. It would be great to remove identical nodes from the new state so only the new files will be left).
I would use LINQ to XML like the project below:
Diff in XML files with LINQ:
http://www.codeproject.com/KB/linq/LinqDiff.aspx
If you'd like to do it in code, you could use Microsoft'ss XML Diff and Patch GUI Tool, and although there isn't a great deal of documentation, there is enough that you should be able to easily diff two XML files in code, in a fairly short space of time. I use it in a couple of projects as part of a series of unit tests which ensure that XML files are being generated correctly.
If you just want to view the differences between the two files, then you could just use any decent diff tool.

Reading an XML File with .NET

I am new to xml and unable to find a way to get content in between tags.
My XML file is
<?xml version="1.0" encoding="utf-8"?>
<block1>
<file name="c:\w0.xml">
<word>Text</word>
<number>67</number>
</file>
<file name="c:\w1.xml">
<word>Text</word>
<number>67</number>
</file>
<file name="c:\w2.xml">
<word>Text</word>
<number>67</number>
</file>
</block1>
LINQ to XML is a great place to start. Consider the following code to parse your XML.
string xml = #"<?xml version=""1.0"" encoding=""utf-8""?>
<block1>
<file name=""c:\w0.xml"">
<word>Text</word>
<number>67</number>
</file>
<file name=""c:\w1.xml"">
<word>Text</word>
<number>67</number>
</file>
<file name=""c:\w2.xml"">
<word>Text</word>
<number>67</number>
</file>
</block1>";
XDocument document = XDocument.Parse(xml);
var block = from file in document.Descendants("file")
select new
{
Name = file.Attribute ("name").Value,
Word = file.Element("word").Value,
Number = (int)file.Element("number")
};
foreach (var file in block)
{
Console.WriteLine("{0}\t{1}\t{2}", file.Name, file.Word, file.Number );
}
You can, of course, load the XML directly from a file using XDocument.Load instead of using Parse to read an XML string. XDocument is in the System.Xml.Linq namespace. Frankly, I would start there, but there are other options to work with XML in the System.Xml namespace (XmlReader.Create, etc.).
You need to use an XML Query language. I would recommend LINQ to XML if you're using .Net 3.5 or XPath if you're using something earlier. XPath has the advantage of being an industry standard, but LINQ to XML is a much 'cleaner' API, in my opinion.
How to query XML with an XPath expression by using Visual C# - Tutorial on using XPath
LINQ to XML Video Tutorial
MSDN XPath Examples - From the XPath Reference
Location Paths - Includes text() function for example.

Categories

Resources