Quickly Changing Values of XML Elements Using LINQ

Published 09 May 08 06:33 PM

I've had many questions lately on how you can query for a specific node in an XML document (or fragment) and change it's value using LINQ. (This must mean that people are really starting to use this stuff so I'm pretty excited.) This is really easy to do because you can modify the values of the selected XElements from your queries and that will change the source XML.

Here's an example:

Imports <xmlns="urn:mycompany:examples:plants">

Module Module1

    Sub Main()
        Dim plants = <?xml version="1.0" encoding="ISO-8859-1"?>
                     <CATALOG xmlns="urn:mycompany:examples:plants">
                         <PLANT>
                             <COMMON>Bloodroot</COMMON>
                             <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
                             <ZONE>4</ZONE>
                             <LIGHT>Mostly Shady</LIGHT>
                             <PRICE>$2.44</PRICE>
                             <AVAILABILITY>031599</AVAILABILITY>
                         </PLANT>
                         <PLANT>
                             <COMMON>Columbine</COMMON>
                             <BOTANICAL>Aquilegia canadensis</BOTANICAL>
                             <ZONE>3</ZONE>
                             <LIGHT>Mostly Shady</LIGHT>
                             <PRICE>$9.37</PRICE>
                             <AVAILABILITY>030699</AVAILABILITY>
                         </PLANT>
                         <PLANT>
                             <COMMON>Marsh Marigold</COMMON>
                             <BOTANICAL>Caltha palustris</BOTANICAL>
                             <ZONE>4</ZONE>
                             <LIGHT>Mostly Sunny</LIGHT>
                             <PRICE>$6.81</PRICE>
                             <AVAILABILITY>051799</AVAILABILITY>
                         </PLANT>
                     </CATALOG>

        Dim q = From plant In plants...<PLANT> _
                Where plant.<COMMON>.Value = "Columbine" _
                Select plant

        For Each item In q
            q.<PRICE>.Value = "$49.99"
            q.<LIGHT>.Value = "Full Sun"
        Next

        plants.Save("plants.xml")
     
    End Sub

End Module

Couple things to note above, remember to import any namespaces being used in the XML otherwise your query will yield no results. And remember you can get XML IntelliSense if you import a schema (this is really easy, watch this). Of course, you can load the XML from a file (or URI) instead of using a literal and and get the same results.

Dim plants = XDocument.Load("plants.xml")

Dim q = From plant In plants...<PLANT> _
        Where plant.<COMMON>.Value = "Columbine" _
        Select plant

For Each item In q
    q.<PRICE>.Value = "$49.99"
    q.<LIGHT>.Value = "Full Sun"
Next

plants.Save("plants.xml")

In this example we're overwriting the source document, plants.xml, with our new values. Both examples produce this resulting XML:

<?xml version="1.0" encoding="iso-8859-1"?>
<CATALOG xmlns="urn:mycompany:examples:plants">
  <PLANT>
    <COMMON>Bloodroot</COMMON>
    <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
    <ZONE>4</ZONE>
    <LIGHT>Mostly Shady</LIGHT>
    <PRICE>$2.44</PRICE>
    <AVAILABILITY>031599</AVAILABILITY>
  </PLANT>
  <PLANT>
    <COMMON>Columbine</COMMON>
    <BOTANICAL>Aquilegia canadensis</BOTANICAL>
    <ZONE>3</ZONE>
    <LIGHT>Full Sun</LIGHT>
    <PRICE>$49.99</PRICE>
    <AVAILABILITY>030699</AVAILABILITY>
  </PLANT>
  <PLANT>
    <COMMON>Marsh Marigold</COMMON>
    <BOTANICAL>Caltha palustris</BOTANICAL>
    <ZONE>4</ZONE>
    <LIGHT>Mostly Sunny</LIGHT>
    <PRICE>$6.81</PRICE>
    <AVAILABILITY>051799</AVAILABILITY>
  </PLANT>
</CATALOG>
Enjoy!

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# Christopher Steen said on May 10, 2008 12:58 AM:

Sharepoint SharePoint as a WCF Host [Via: Sahil Malik ] SharePoint 2007 as a WCF host - Step #4, Write...

# Damien said on May 12, 2008 1:30 AM:

Great article, Beth.  Productivity is skyrocketing with Linq. :)

Is it possible to do stuff like querying an entire element (along with all of its children, grandchildren etc) and inserting that element into another XML document? (without looping through the entire hierarchy)

# Konstantin Samsonov said on May 12, 2008 3:40 AM:

This is fine.

But why Visual Studio change my Linq xml like (fragment)

<!                <- space />

<SomeText> </SomeText>

to

<SomeText></SomeText>

and not preserve my spaces.

It isn't good testing for such helpful product. Wait for sp1 8-).

# Fred said on May 12, 2008 8:30 PM:

Can code like this be run from a web page?  We have an ASP page the hits an Access db and the ISP keeps messing up the Access file.  Would something like this simplify our file problem?

Thanks, Fred

# Luciano Evaristo Guerche (Gorše) said on May 15, 2008 9:58 PM:

Beth,

Which Imports should I set so that the following code works? If possible send reply(ies) to my twitter account at @guerchele. Thanks in advance.

'Each one? Both?

'Imports <xmlns:p="urn:mycompany:examples:plants">

'Imports <xmlns:p="urn:mycompany:examples:people">

Module Module1

   Sub Main()

       Dim plants = <?xml version="1.0" encoding="ISO-8859-1"?>

                    <CATALOG xmlns:p="urn:mycompany:examples:plants">

                        <PLANT>

                            <COMMON>Bloodroot</COMMON>

                            <BOTANICAL>Sanguinaria canadensis</BOTANICAL>

                            <ZONE>4</ZONE>

                            <LIGHT>Mostly Shady</LIGHT>

                            <PRICE>$2.44</PRICE>

                            <AVAILABILITY>031599</AVAILABILITY>

                        </PLANT>

                        <PLANT>

                            <COMMON>Columbine</COMMON>

                            <BOTANICAL>Aquilegia canadensis</BOTANICAL>

                            <ZONE>3</ZONE>

                            <LIGHT>Mostly Shady</LIGHT>

                            <PRICE>$9.37</PRICE>

                            <AVAILABILITY>030699</AVAILABILITY>

                        </PLANT>

                        <PLANT>

                            <COMMON>Marsh Marigold</COMMON>

                            <BOTANICAL>Caltha palustris</BOTANICAL>

                            <ZONE>4</ZONE>

                            <LIGHT>Mostly Sunny</LIGHT>

                            <PRICE>$6.81</PRICE>

                            <AVAILABILITY>051799</AVAILABILITY>

                        </PLANT>

                    </CATALOG>

       Dim people = <?xml version="1.0" encoding="ISO-8859-1"?>

                    <CATALOG xmlns:p="urn:mycompany:examples:people">

                        <PERSON>

                            <NAME>blah blah blah</COMMON>

                        </PERSON>

                        <PERSON>

                            <NAME>blah blah blah</COMMON>

                        </PERSON>

                        <PERSON>

                            <NAME>blah blah blah</COMMON>

                        </PERSON>

                    </CATALOG>

       plants.Save("plants.xml")

       people.Save("people.xml")

   End Sub

End Module

# radiolistener said on June 1, 2008 9:57 AM:

Hi Beth,

This is exactly what I was looking for.  I watched some more of your videos and I found the one with xml tool.  I assume it is the video you reference in this article.  Now, when I am parsing xml, I get the entire typeahead feature.  It's really a boon.

I had been working on Vista and VS2008 at home, to get ahead of the curve at work.  From describing my findings, I was able to get both approved at work.

The LINQ alone is going to make my life so much easier!  We are on this push to make all our applications configurable via xml config files.  This specification is so much easier met when I have tools like LINQ, I am one happy camper.

Thanks again, You're the best!

John.

# Marc said on June 10, 2008 10:24 AM:

Lucian and others, to get this working add the following import:

Imports &lt;xmlns="urn:mycompany:examples:plants"&gt;

# Marc said on June 10, 2008 10:25 AM:

Lucian and others, to get this working add the following import:

Imports <xmlns="urn:mycompany:examples:plants">

# Joycode@Ab110.com said on September 27, 2008 5:49 AM:

[原文作者]: Beth Massi [原文链接]: Quickly Changing Values of XML Elements Using LINQ 最近我在考虑一些关于如何使用LINQ查询XML文档

# Vincent said on March 27, 2009 9:02 PM:

Hi Beth,

First of all, I like your "how do I" video series! I've seen many of them and are a great help! Now I'm trying to learn LINQ to XML and I've read and viewed most (if not all) of your posts and videos though I still have a problem and hope you can offer some advice.

Let's say you want to create a diary and store each day in one xml file. After one year a new empty xml file will be created to reduce file size. How would I make this xml file containing data for a whole year searchable using LINQ?

example:

<day>

 <Date>28/03/2009</Date>

 <Wheather>Rainy</Wheather>

 <Where_was_I>At home</Where_was_I>

 <Story_morning>some text here what i was doing in the morning on this particular day</Story_morning>

 <Story_afternoon>some text here what i was doing in the afternoon on this particular day</Story_afternoon>

 <Story_evening>some text here what i was doing in the evening on this particular day</Story_evening>

 <Had_to_work>False</Had_to_work>

 <Friends_met>Erik, Eline, Alex</Friends_met>

</Day>

My question:

How would my LINQ querie look if I want to search the story field "<Story_evening>" for a specific searchstring like "party" (contains the word) in a specific date range (between two dates).

I supose this might result in a fairly big request for you to answer it but any help would be appreciated.

Obviously one would probably use a database instead but I cannot use databes for this purpose since I don't have SQL server at my disposal.

Thank you very much (for your video series and maybe for your help on this ;))

Vincent

ps

Sorry for my spelling my english is a bit 'rusty'

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required

About Beth Massi

Beth is a Program Manager on the Visual Studio Community Team at Microsoft and is responsible for producing and managing content for business application developers, driving community features and team participation onto MSDN Developer Centers (http://msdn.com), and helping make Visual Studio one of the best developer tools in the world. She also produces regular content on her blog (http://blogs.msdn.com/bethmassi), Channel 9, and a variety of other developer sites and magazines. As a community champion and a long-time member of the Microsoft developer community she also helps with the San Francisco East Bay .NET user group and is a frequent speaker at various software development events. Before Microsoft, she was a Senior Architect at a health care software product company and a Microsoft Solutions Architect MVP. Over the last decade she has worked on distributed applications and frameworks, web and Windows-based applications using Microsoft development tools in a variety of businesses. She loves teaching, hiking, mountain biking, and driving really fast.

This Blog

Syndication

Page view tracker