views:

32

answers:

1

Hello...I have an XML as follows.

<AFConfig>
 <Geographies>
  <Geography id="Place1" description="NicePlace">
   <MetaData>
    <Services>
     <Service>
     ...
     ...
     </Service>
    </Services>
   </MetaData>
   <Systems>
    <DefaultSystem systemName="SYSONE" server=http"//192.168.0.0" />
   </Systems>
  </Geography>
 <Geographies> 
</AFConfig>

What I want to do is this.

  1. Clone the element Geography and add it as a Sibling (i.e., Child to Geographies)
  2. Update "id", "description" with new values AND
  3. update the systemName with new value

My Code.

XDocument xd_Document = XDocument.Load(s_FileName);
XElement xe_Element = (from xe in xd_Document.XPathSelectElements(s_Element)
                       where xe.Attribute(s_IdAttr).Value == s_Value
                       select xe).SingleOrDefault();
XElement xe_NewElement = CloneElement(xe_Element)
foreach(KeyValuePair<string, string> s in d_AttrValue)
    xe_NewElement.Attribute(s.Key).Value = d_AttrValue[s.Key];
xe_Element.Parent.Add(xe_NewElement);
xd_Document.Save(s_destFileName);

I pass to this method the following parameters string s_FileName, string s_destFileName, string s_Element, string s_IdAttr, string s_Value, Dictionary d_AttrValue

With this code, I am able to modify the id and description attributes.

Question: How will I modify the DefaultSystem attribute systemName with a value?

NB: I have the same code for Modification of existing Element sans the Creation of New Element. Again, I run into the same problem. A generic solution would be preferred.

A: 
xe_NewElement.Element("Systems")
    .Element("DefaultSystem")
    .Attribute("systemName")
    .Value = "Enter your value here";

I believe should do what you need.

EDIT:

var attribute = ((IEnumerable)xe_NewElement.XPathEvaluate("Systems/DefaultSystem/@systemName"))
    .Cast<XAttribute>().FirstOrDefault();

attribute.Value = "Enter your value here";

Should allow you to so it generically by passing in a list of xpaths and values.

Andy Lowry
Andy: Thanks. But, my code is part of a Function. And I would prefer not to hard-code the child element names. Is there a way, a generic way so to speak to solve this problem?
Kanini
I've edited my answer to include a more generic solution. Although it's not pretty, there must be a better solution.
Andy Lowry
Andy: The above edited piece of code comes up with an error of Using the generic type 'System.Collections.Generic.IEnumerable<T>' requires '1' type arguments
Kanini
You probably need to add using System.Generic; to you cs file.
Andy Lowry
Andy: Thanks. I will take a check at it.
Kanini