【问题标题】:Linq to XML with nested Dictionary and Array带有嵌套字典和数组的 Linq to XML
【发布时间】:2014-03-03 12:11:05
【问题描述】:

我正在开发 Windows Phone 8 应用程序:

我有这样的文件:

<array>
    <dict>
        <key>SubTopics</key>
        <array>
            <dict>
                <key>ID</key>
                <array>
                    <string>CD1</string>
                    <string>CD2</string>
                    <string>CD3</string>
                    <string>CD4</string>    
                </array>
                <key>Title</key>
                <string>Miscellaneous</string>
                <key>Desc</key>
                <string> this is just a text</string>
                <key>HasItems</key>
                <true/>
            </dict>
            <dict>
                <key>ID</key>
                <array>
                    <string>DDC1</string>
                    <string>DDC2</string>
                    <string>DDC3</string>
                    <string>DDC4</string>
                    <string>DDC5</string>
                </array>
                <key>Title</key>
                <string>Miscellaneous One</string>
                <key>Desc</key>
                <string> this is just a text</string>
                <key>HasItems</key>
                <true/>
            </dict>
      </array>
      <key>MainTitle</key>
      <string>Data</string>
    </dict>
    <dict>
        <key>SubTopics</key>
        <array>
            <dict>
                <key>ID</key>
                <array>
                    <string>SSD1</string>
                    <string>SS2</string>
                    <string>SS3</string>
                    <string>SS4</string>    
                </array>
                <key>Title</key>
                <string>Goblins</string>
                <key>Desc</key>
                <string> this is just a text</string>
                <key>HasItems</key>
                <true/>
            </dict>
            <dict>
                <key>ID</key>
                <array>
                    <string>ADC1</string>
                    <string>ADC2</string>
                    <string>ADC3</string>
                    <string>ADC4</string>
                    <string>DDC5</string>
                </array>
                <key>Title</key>
                <string>Tracks</string>
                <key>Desc</key>
                <string> this is just a text</string>
                <key>HasItems</key>
                <true/>
            </dict>
      </array>
      <key>MainTitle</key>
      <string>Data Two</string>
    </dict>
</array>

如何解析这个?

是这样的:

MainTitle 

   --SubTitle

  ---ID

  ---Desc

  ---Boolean Value
 MainTitle 

   --SubTitle

  ---ID

  ---Desc

  ---Boolean Value

基本上是带有键和值数组列表的字典列表。

我试过这样但它不完整:

List<MyObject> topics = (from plist in doc.Root.Element("array").Elements("dict")
                                  select new MyObject
                                  {
                                      MainTitle = (string)plist.Element("string"),
                                      ListOfSubTitles = plist.Element("array")
                                                   .Elements("dict")
                                                   .Elements("string")
                                                   .Select(s => (string)s)
                                                   .ToList(),
                                      ListOfIDs = plist.Element("array")
                                                    .Elements("dict")
                                                    .Elements("array")
                                                    .Elements("string")
                                                    .Select(s => (string)s)
                                                    .ToList()
                                  }).ToList();

【问题讨论】:

  • 您的 xml 不好,因为它假定元素的某些特定顺序 key,value,key,value....。如果您没有从外部站点获取它,请更改它...
  • @L.B 不正确,我已经在 J​​AVA 中解析了相同的 Xml,只是我被困在如何在 c# 中执行它
  • Goofy,我不是说它无效,我说的是,在 xml 中依靠元素的顺序是一种不好的做法。更好的方法是列出&lt;KeyValue&gt;&lt;Key&gt;...&lt;/Key&gt;&lt;Value&gt;....&lt;/Value&gt;&lt;/KeyValue&gt;
  • @L.B 是的,但我必须这样做,没有其他选择,你能帮帮我吗?
  • 这是来自 iOS 的 pList 文件 - 他正在将 iPhone 应用程序转换为 Windows - 就像我一样 - 感谢您提出问题 :-)

标签: c# wpf linq parsing windows-phone-8


【解决方案1】:

好的,这是一个可以解析你的 xml 的小类:

public class Parser
{
    public List<Dictionary<string, object>> Parse(XElement root)
    {
        var result = new List<Dictionary<string, object>>();

        foreach (var e in root.Elements())
        {
            if (e.Name == "dict")
            {
                result.Add(ParseDict(e));
            }
        }

        return result;
    }

    private Dictionary<string, object> ParseDict(XElement element)
    {
        var dict = new Dictionary<string, object>();

        foreach (var subelement in element.Elements())
        {
            if (subelement.Name == "key")
            {
                dict.Add(subelement.Value, ParseValue(subelement.ElementsAfterSelf().First()));        
            }
        }

        return dict;
    }

    private object ParseValue(XElement valueElement)
    {
        if (valueElement.Name == "string")
        {
            return valueElement.Value;
        }

        if (valueElement.Name == "array")
        {
            return new List<object>(valueElement.Elements().Select(e => ParseValue(e)));
        }

        if (valueElement.Name == "dict")
        {
            return ParseDict(valueElement);
        }

        if (valueElement.Name == "true")
        {
            return true;
        }

        if (valueElement.Name == "false")
        {
            return false;
        }

        return null;
    }
}

它是这样使用的:

        var parser = new Parser();
        var doc = XDocument.Load(<path to xml file>);

        var result = parser.Parse(doc.Root);

解析器非常粗糙,并对 xml 做出假设。正如之前的 cmets 所指出的,像这样使用 xml 并不是最好的方法,因为元素的位置很重要。此外,在解析器中使用“对象”也不是一个好的解决方案,但如果您想避免这种情况,解析器会变得更加先进。

【讨论】:

  • 但是在这里我将如何使用 MainTitle 获得 ListOfSubTitles ?还是 ListOfSubTitles 的 ListOfIDs ?,我的意思是基于我需要 vlaues 的键
  • 由于您的xml格式,您无法真正解析它。您需要遍历元素并一路保存数据。您可以为此使用 XDocument 或 XmlReader。创建一个工作示例需要一些时间,所以必须等到我下班。
  • 不要担心解析器很粗糙,这是在应用启动时加载数据的一次性任务。对于许多应用程序来说,这是从 iOS 转换到 Windows 的过程中非常重要的一部分。 iOS pList 文件看起来都是这样,因此您的解决方案具有非常广泛的用途。我在下面的另一个答案中添加了一些代码 sn-p 以使人们能够测试输出。
【解决方案2】:

我几乎直接使用了 Hakan 的 Parser 类:我需要一个整数元素,但不需要 true 或 false - 简单的编辑。这个 sn-p 可能会帮助人们测试他们的代码。我已经重命名了 Hakan 的一些符号以适合我的项目。

private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        List<Dictionary<string, object>> topicsList = topicParser.Parse(topicsXDocument.Root);
        Console.WriteLine("The Topics List contains:");
        foreach (Dictionary<string, object> topic in topicsList)
        {
            foreach (KeyValuePair<string, object> element in topic)
            {
                string name = element.Key;
                object content = element.Value;
                Console.WriteLine("Key: {0}, Value: {1}", name, content.ToString());
            }
        }

    }

【讨论】:

    猜你喜欢
    • 2019-07-19
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多