Search code examples
c#linqxelement

Linq xElement read - I need to read a parent value whilst reading nested dependencies


As title indicates I need to read a parent value whilst selecting dependency values. Whilst loading the Symbols into a collection I also need to add the 'CategoryDescription' value for each symbol.

The code I am using to read the symbol data is this but I cannot work out how to add the 'CategoryDescription' value. I don't want to add it as another element under Symbol if I can help it.

Thanks, Jim

    private void UserCategories_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        //
        if (e.AddedItems.Count <= 0) return;

        _userSymbolEntries.Clear();

        var categorySet = UserCategories.SelectedItem.ToString();

        var categx = XElement.Load(catLoadLocation);

        var catResults = categx.Descendants("Category")

            .Descendants("CategoryDescription")
            //.Where(ee => ee.Value == categorySet)
            .Select(ee => ee.Parent)
            .Descendants("Symbol")
            .Select(ee => new
            {
                xDescription = ee.Descendants("Description").FirstOrDefault().Value,
                xFontFamily = ee.Descendants("FontFamily").FirstOrDefault().Value,
                xUnicodeValue = ee.Descendants("UnicodeValue").FirstOrDefault().Value,
                xText = (ee.Descendants("UnicodeValue").FirstOrDefault().Value).ToString(),
                xState = ee.Descendants("UserSymbolState").FirstOrDefault().Value
            });

        var i = 0;
        foreach (var catResult in catResults)
        {
            var use = new UserSymbolEntry {Description = catResult.xDescription};
            TypeConverter tc = TypeDescriptor.GetConverter(typeof(FontFamily));
            use.FontFamily = (FontFamily)tc.ConvertFromString(catResult.xFontFamily);
            use.UnicodeValue = catResult.xUnicodeValue;
            var x = "0x" + catResult.xUnicodeValue;  //    0x0041;  ((char) x).ToString();
            var y = Convert.ToInt32(x, 16);

            switch (catResult.xState)
            {
                case "Normal":
                    use.UserSymbolState = UserSymbolState.Normal;
                    break;

                case "Added":
                    use.UserSymbolState = UserSymbolState.Added;
                    break;

                case "Deleted":
                    use.UserSymbolState = UserSymbolState.Deleted;
                    break;
            }

            use.Text = ((char)y).ToString();
            use.Id = i++;
            if (catResult.xFontFamily == categorySet)
                _userSymbolEntries.Add(use);

        }
    }

The XML looks like this

<?xml version="1.0" encoding="utf-8" ?>
<CMCategories>
  <Category>
    <Name>Test</Name>
    <CategoryDescription>FontFamily Change</CategoryDescription>
    <Symbol>
      <Description>A</Description>
      <FontFamily>Courier New</FontFamily>
      <UnicodeValue>0041</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
    <Symbol>
      <Description>A</Description>
      <FontFamily>Vani</FontFamily>
      <UnicodeValue>0041</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
    <Symbol>
      <Description>A</Description>
      <FontFamily>Segoe UI Symbol</FontFamily>
      <UnicodeValue>0041</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
  </Category>
  <Category>
    <Name>Arrows</Name>
    <CategoryDescription>Various Arrows</CategoryDescription>
    <Symbol>
      <Description>Left Arrow</Description>
      <FontFamily>Segoe UI Symbol</FontFamily>
      <UnicodeValue>2190</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
    <Symbol>
      <Description>Up Arrow</Description>
      <FontFamily>Segoe UI Symbol</FontFamily>
      <UnicodeValue>2191</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
    <Symbol>
      <Description>Right Arrow</Description>
      <FontFamily>Segoe UI Symbol</FontFamily>
      <UnicodeValue>2192</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
    <Symbol>
      <Description>Down Arrow</Description>
      <FontFamily>Segoe UI Symbol</FontFamily>
      <UnicodeValue>2193</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
  </Category>
  <Category>
    <Name>MiscTech</Name>
    <CategoryDescription>Miscellaneous Technical</CategoryDescription>
    <Symbol>
      <Description>Double Right</Description>
      <FontFamily>Segoe UI Symbol</FontFamily>
      <UnicodeValue>23E9</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
    <Symbol>
      <Description>Double Left</Description>
      <FontFamily>Segoe UI Symbol</FontFamily>
      <UnicodeValue>23EA</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
    <Symbol>
      <Description>Double Up</Description>
      <FontFamily>Segoe UI Symbol</FontFamily>
      <UnicodeValue>23EB</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
    <Symbol>
      <Description>Double Down</Description>
      <FontFamily>Segoe UI Symbol</FontFamily>
      <UnicodeValue>23EC</UnicodeValue>
      <UserSymbolState>Normal</UserSymbolState>
    </Symbol>
  </Category>
</CMCategories>

Solution

  • Try this

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            const string FILENAME = @"c:\temp\test.xml";
            static void Main(string[] args)
            {
    
                XDocument doc = XDocument.Load(FILENAME);
    
                var results = doc.Descendants("Category").Select(x => new {
                    name = (string)x.Element("Name"),
                    categoryDescription = (string)x.Element("CategoryDescription"),
                    symbols = x.Elements("Symbol").Select(y => new {
                        description = (string)y.Element("Description"),
                        fontFamily = (string)y.Element("FontFamily"),
                        unicodeValue = int.Parse((string)y.Element("UnicodeValue"), System.Globalization.NumberStyles.HexNumber),
                        userSymbolState = (string)y.Element("UserSymbolState")
                    }).ToList()
                }).ToList();
            }
        }
    }