Update an Existing Element Using Linq

E

Edwin

I am trying to write an application among which one of the functions is to
determine the number of unique extensions found in a directory and all of
its sub directories. I am trying to use Linq to XML to do this.

Below is the code being used to accomplish what I am trying to do. In the
"if" statement, I am trying to update the <Count></Count> Element to
"TESTING". However what I will really want is to add 1 to the existing
numerical value.

Your help is greatly appreciated!


System.IO.FileInfo myCurrentFile;
System.Xml.Linq.XElement myFileCountCurrentElement;

var Extensions = new XElement("Count", (from Extension in
_myFileExtensionCount.LinqXDocument.Descendants("Extension") where
Extension.Element("Name").Value == myCurrentFile.Extension.ToLower()
select new
{
Name =
Extension.Element("Name").Value,
Count =
Extension.Element("Count").Value,
}));


// An unaccounted file extension has been found. Let's add it.
if (Extensions.IsEmpty == true)
{
myFileCountCurrentElement = _myFileExtensionCount.LinqXDocument.Root;
myFileCountCurrentElement =
_myFileExtensionCount.AppendXmlElement(myFileCountCurrentElement,
"Extension", null);
_myFileExtensionCount.AppendXmlElement(myFileCountCurrentElement,
"Name", myCurrentFile.Extension.ToLower());
_myFileExtensionCount.AppendXmlElement(myFileCountCurrentElement,
"Count", "1");
}
else
{
Extensions.SetValue("TESTING");
}

Below is the XML output that I am getting.


<?xml version="1.0" encoding="utf-8" ?>
- <FileExtensions>
- <Extension>
<Name>.m4b</Name>
<Count>1</Count>
</Extension>
- <Extension>
<Name>.docx</Name>
<Count>1</Count>
</Extension>
- <Extension>
<Name>.doc</Name>
<Count>1</Count>
</Extension>
- <Extension>
<Name>.xls</Name>
<Count>1</Count>
</Extension>
- <Extension>
<Name>.xlsx</Name>
<Count>1</Count>
</Extension>
</FileExtensions>
 
M

Martin Honnen

Edwin said:
Below is the XML output that I am getting.


<?xml version="1.0" encoding="utf-8" ?>
- <FileExtensions>
- <Extension>
<Name>.m4b</Name>
<Count>1</Count>
</Extension>
- <Extension>
<Name>.docx</Name>
<Count>1</Count>
</Extension>
- <Extension>
<Name>.doc</Name>
<Count>1</Count>
</Extension>
- <Extension>
<Name>.xls</Name>
<Count>1</Count>
</Extension>
- <Extension>
<Name>.xlsx</Name>
<Count>1</Count>
</Extension>
</FileExtensions>

Here is an example that adds 1 to each Count element in the sample above:

XDocument doc = XDocument.Parse(@"<FileExtensions>
<Extension>
<Name>.m4b</Name>
<Count>1</Count>
</Extension>
<Extension>
<Name>.docx</Name>
<Count>1</Count>
</Extension>
<Extension>
<Name>.doc</Name>
<Count>1</Count>
</Extension>
<Extension>
<Name>.xls</Name>
<Count>1</Count>
</Extension>
<Extension>
<Name>.xlsx</Name>
<Count>1</Count>
</Extension>
</FileExtensions>");
foreach (XElement ext in doc.Root.Elements("Extension")) {
ext.SetElementValue("Count", (int)ext.Element("Count")
+ 1);
}
doc.Save(Console.Out);

HTH
 
E

Edwin

I do not want to update every <Count></Count> for every extension. I just
want to udpate the <Count></Count> only if the <Name></Name> applies for the
current extension being looked at.

For example:

<Extension>
<Name>.m4b</Name>
<Count>10</Count>
</Extension>
<Extension>
<Name>.docx</Name>
<Count>7</Count>
</Extension>
<Extension>
<Name>.doc</Name>
<Count>324</Count>
</Extension>
<Extension>
<Name>.xls</Name>
<Count>98</Count>
</Extension>
<Extension>
<Name>.xlsx</Name>
<Count>45</Count>
</Extension>
</FileExtensions>
 
M

Martin Honnen

Edwin said:
I do not want to update every <Count></Count> for every extension. I
just want to udpate the <Count></Count> only if the <Name></Name>
applies for the current extension being looked at.

Well my code was just meant as an example.
Here is a different example that updates Count for one Extension element:

XDocument doc = XDocument.Parse(@"<FileExtensions>
<Extension>
<Name>.m4b</Name>
<Count>10</Count>
</Extension>
<Extension>
<Name>.docx</Name>
<Count>7</Count>
</Extension>
<Extension>
<Name>.doc</Name>
<Count>324</Count>
</Extension>
<Extension>
<Name>.xls</Name>
<Count>98</Count>
</Extension>
<Extension>
<Name>.xlsx</Name>
<Count>45</Count>
</Extension>
</FileExtensions>");

string exampleExt = ".docx";
XElement extension = doc.Root.Elements("Extension").Where(e
=> e.Element("Name").Value == exampleExt).FirstOrDefault();
if (extension != null)
{
extension.SetElementValue("Count", 1 +
(int)extension.Element("Count"));
}
doc.Save(Console.Out);
 
E

Edwin

Excellent! It worked!

I am not sure I understand it but it did exactly what I wanted it to do. I
now have to learn what exactly is happening.

Thanks for your help!
 
M

Martin Honnen

Edwin said:
I am not sure I understand it but it did exactly what I wanted it to
do. I now have to learn what exactly is happening.

It is not that complicated, just uses LINQ to XML properties (like Root)
and methods (like Elements("Extension")) and LINQ queries with a lambda
expression:

string exampleExt = ".docx";
XElement extension = doc.Root.Elements("Extension").Where(e
=> e.Element("Name").Value == exampleExt).FirstOrDefault();
if (extension != null)
{
extension.SetElementValue("Count", 1 +
(int)extension.Element("Count"));
}

So doc.Root accesses the root element, doc.Root.Elements("Extension")
all "Extension" child elements of the Root. Then the LINQ Where method
filters those elements with the lambda expression
e => e.Element("Name").Value == exampleExt
meaning it takes those "Extension" elements which have a "Name" child
element where the Value is equal to exampleExt.

FirstOrDefault() simply means we want only the first of those filtered
elements or null if there is noone.

Once we have found an element all we need to do is set the value of the
"Count" child element using SetElementValue by incrementing the value by
one, to do that we can cast the "Count" child element to an int and add
1. That cast works as XElement provides
http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.op_explicit.aspx
to cast do a lot of CLR types.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top