开发者

How can I rewrite this Linq to XML query?

I am preferring LINQ to XML over XMLReader because it feels much easier to use. However, I know I'm doing it wrong somewhere. I'm not looking for faster execution or anything, just a cleaner rewrite. I can't tell if it'll fit cleanly into the from foo in bar where foo is some condition form, but there's g开发者_运维知识库ot to be a cleaner way.

I am not using anonymous objects here and instead outputting as strings because I am excluding some code which will adapt the data into existing objects - however, it is kind of a messy structure currently which I need to refactor.

My XML looks like this.

<?xml version="1.0" encoding="utf-8" ?>
<entity name="Something">
  <Component type="RenderComponent">
    <Material type="string">fur</Material>
    <Reflectiveness type="int">678</Reflectiveness>
  </Component>

  <Component type="HealthComponent">
    <Sound type="int">60</Sound>
  </Component>
</entity>

And my code:

static void Main(string[] args)
{
    XDocument xdoc = XDocument.Load(@"..\..\XMLFile1.xml");
    List<string> comNames = new List<string>();
    Dictionary<string, string> paramValues = new Dictionary<string, string>();
    List<string> paramTypes = new List<string>();

    foreach (XElement e in xdoc.Root.Elements("Component"))
    {
        string type = e.Attribute("type").Value;
        foreach(XElement param in e.Elements())
        {
            paramValues.Add(param.Name.LocalName, param.Value);
            paramTypes.Add(param.Attributes().First().Value);
        }
        Console.WriteLine(" \n\n\n");
        comNames.Add(type);
    }

}

Giving outputs of:

comNames - RenderComponent, HealthComponent

paramValues - (Material, fur), (Reflectiveness, 678), (Sound, 60)

paramTypes - string, int, int

If it clears it up somewhat, the general layout of the file:

  • Root node entity with a name attribute (forgot in this example)
  • n Component nodes with type attributes
  • Each Component node has a number of child nodes which have names, a type attribute, and a value.


I think, you can do something like this:

XDocument xdoc = XDocument.Load(@"..\..\XMLFile1.xml");
var data = 
xdoc.Root.Elements("Component")
         .SelectMany(e => new
                          {
                            type = e.Attribute("type").Value, 
                            paramValues = e.Elements()
                                           .Select(x => new KeyValuePair<string,
                                                                         string>
                                                              (x.Name.LocalName, 
                                                               x.Value)),
                            paramType = e.Elements()
                                         .Select(x => x.Attributes().First()
                                                                     .Value)
                          });

List<string> comNames = data.Select(x => x.type).ToList();
List<string> paramTypes = data.Select(x => x.paramType).ToList();
Dictionary<string, string> paramValues = data.Select(x => x.paramValues)
                                             .ToDictionary(x => x.Key, 
                                                           x => x.Value);

But honestly, I think your original code is just fine.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜