开发者

c#Linq To XML Same element names

I have a small problem. I have an XML file where all the level 1 Elements have the same Element name and are distinguishable by a Name attribute. I cannot change the XML file.

Here is an example of the XML file:

<XProperty Name="DeviceInfo" FileVersion="1" xmlns="x-schema:XPropertySchema.xml" xmlns:dt="urn:schemas-microsoft-com:datatypes">
<Value dt:dt="i4">34</Value>
<Reserved>0</Reserved>
<XProperty Name="Manufacturer">
</XProperty>
<XProperty Name="ModelName">
    <Value>Advantage N-SL</Value>
    <Reserved>0</Reserved>
</XProperty>
<XProperty Name="SerialNumber">
    <Value>N40000</Value>
    <Reserved>0</Reserved>
</XProperty>

Now, what I need, in c# & Linq to XML, is some code that will set the value of Value sub-node of a specific XProperty node. For example, for the XProperty node with Name 'SerialNumber' set the value of the Value sub-node to 'XYZ'.

Second Example: The value to change could also be a few descendants down (this is variable) xml:

 <XProperty Name="Versions">
        <XProperty Name="Parameters" Persistent="yes">
            <ShortDescription>Name</ShortDescription>
            <LongDescription>Version object</LongDescription>
            <Reserved>0</Reserved>
            <XProperty Name="Index" Persistent="yes">
 开发者_如何学C               <ShortDescription>VersionIndex</ShortDescription>
                <Value dt:dt="i4">1</Value>
                <Reserved>0</Reserved>
            </XProperty>
        </XProperty>
    </XProperty>

I need to change the value of Index.

The Class that contains what element to change:

public class XmlChanger
    {
        public string File { get; set; }
        public string Key { get; set; }
        public XmlChanger ChildKey { get; set; }
        public string ChildKeyString { get; set; }
    }

So With the same code I need example 1 to work and also example 2.

In some cases the Value sub-node might not exist, in which case I need to add it.

Any idea what the best way to do this is?

ps. I'm having some problem explaining but I hope someone get's what the meaning of it is.

Thanks in advance!


Use something like this:

var doc = XDocument.Parse(xml);
var element = doc.Root.Elements().
                  Where(x => x.Name.LocalName == "XProperty" && 
                             x.Attributes().Any(
                                 y => y.Name == "Name" &&
                                 y.Value == "DeviceInfo")
                       ).SingleOrDefault();
if(element != null)
{    
    // change it
}
else
{
    // add a new one
    doc.Root.Add(new XElement(doc.Root.Name.Namespace+ "XProperty", 
                              new XAttribute("Name", "DeviceInfo2")));
}

I used this XML definition:

var xml = @"<xml xmlns=""x-schema:XPropertySchema.xml"" xmlns:dt=""urn:schemas-microsoft-com:datatypes"">
<XProperty Name=""DeviceInfo"" FileVersion=""1"">
<Value dt:dt=""i4"">34</Value>
<Reserved>0</Reserved>
</XProperty>
<XProperty Name=""Manufacturer"">
</XProperty>
<XProperty Name=""ModelName"">
    <Value>Advantage N-SL</Value>
    <Reserved>0</Reserved>
</XProperty>
<XProperty Name=""SerialNumber"">
    <Value>N40000</Value>
    <Reserved>0</Reserved>
</XProperty>
</xml>";

I created this code in LINQPad and used a string variable to hold the xml file. In this scenario, I need Parse. If you want to load the XML directly from a file, XDocument.Load is the right way


var docx = XDocument.Load("someUri");

var elements = docx.Elements(XName.Get("XProperty")).Where(x => x.Attributes().Count(a => a.Name == XName.Get("Name") && a.Value == "SerialNumber") > 0);

foreach (var e in elements)
{
    if (e.Elements().Count(x => x.Name == XName.Get("Value")) == 1)
    {
        e.Elements().Single(x => x.Name == XName.Get("Value")).Value = "XYZ";
    }
    else
    {
        e.Add(new XElement(XName.Get("Value"), "XYZ"));
    }
}

I've not made concessions for the Namespace that your XML fragment contains, so you're going to have to add this to the XName.Get() method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜