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

Leave a Comment

(required) 
(optional)
(required) 

About Beth Massi

Beth Massi is a Program Manager on the VS Community Team working with the Visual Basic Team producing developer content on MSDN and her blog (http://blogs.msdn.com/bethmassi). As a VB community champion and a member of the Microsoft community she helps run a .NET user group in the San Francisco Bay Area and is a frequent speaker at various software development events. Before Microsoft she was a Senior Systems Architect at a health care software product company and was a Microsoft Solutions Architect MVP. Over the last decade she has worked on distributed applications and frameworks using Visual Basic.NET, ASP.NET, SQL-Server, and Visual FoxPro. She has worked on various projects including developing object-oriented middle-tier frameworks, COM, .NET, Web and Windows-based applications using Microsoft development tools for a variety of businesses. She loves teaching, mountain biking, and modifying cars.

This Blog

Syndication

Page view tracker