【问题标题】:LINQ to XML join with idrefLINQ to XML 与 idref 连接
【发布时间】:2013-01-30 09:25:04
【问题描述】:

我的 XML 结构如下:

[...]
<Fruits>
   <Fruit>
      <Specification>id_1001_0</Specification> 
      <Weight>23</Weight>
   </Fruit>
</Fruits>
<FruitSpecification id="id_1001_0">
   <Type>Apple</Type>
</FruitSpecification>
[...]

我想使用 Linq to XML 将其读入(非匿名)对象。 假设我有以下代码:

var fruits = from xele in xDoc.Root.Element("Fruits").Elements("Fruit")
             select new Fruit()
             {
                Weight = xele.Element("Weight").Value
             }

如何扩展查询以加入正确的FruitSpecification 标签? 目标是能够这样写:

var fruits = from xele in xDoc.Root.Element("Fruits").Elements("Fruit")
             //some join?
             select new Fruit()
             {
                Weight = xele.Element("Weight").Value,
                Type = xjoinedelement.Element("Type").Value
             }

我希望这是可以理解的,我制作了这个“水果”示例,我的实际 XML 要复杂得多...

【问题讨论】:

    标签: c# .net xml linq-to-xml


    【解决方案1】:

    是的,简单的连接就可以解决问题:

    var fruits = 
        from f in xdoc.Root.Element("Fruits").Elements("Fruit")
        join fs in xdoc.Root.Elements("FruitSpecification")
             on (string)f.Element("Specification") equals (string)fs.Attribute("id")
        select new Fruit()
        {
             Weight = (int)f.Element("Weight"),
             Type = (string)fs.Element("Type")
        };
    

    水果类定义:

    public class Fruit
    {
        public int Weight { get; set; }
        public string Type { get; set; }
    }
    

    【讨论】:

    • 非常感谢,当我尝试这样的方式时,我想我错过了(字符串)部分
    • @Jobo 欢迎 :) 顺便说一句,最好使用转换然后访问 Value 属性(如果节点缺少转换将返回默认值,但访问属性将抛出 NullReferenceException)
    【解决方案2】:

    试试这个:

    class Fruit
    {
        public int Weight { get; set; }
        public string Type { get; set; }
    }
    
    string xml = @"
                <root>
                    <Fruits>
                        <Fruit>
                            <Specification>id_1001_0</Specification> 
                            <Weight>23</Weight>
                        </Fruit>
                        <Fruit>
                            <Specification>id_1002_0</Specification> 
                            <Weight>25</Weight>
                        </Fruit>
                    </Fruits>
                    <FruitSpecification id='id_1001_0'>
                        <Type>Apple</Type>
                    </FruitSpecification>
                    <FruitSpecification id='id_1002_0'>
                        <Type>Orange</Type>
                    </FruitSpecification>
                </root>";
    XElement element = XElement.Parse(xml);
    
    IEnumerable<XElement> xFruites = element.Descendants("Fruit");
    IEnumerable<XElement> xFruitSpecifications = element.Descendants("FruitSpecification");
    IEnumerable<Fruit> frits = xFruites.Join(
        xFruitSpecifications,
        f => f.Element("Specification").Value,
        s => s.Attribute("id").Value,
        (f, s) =>
        new Fruit
            {
                Type = s.Element("Type").Value,
                Weight = int.Parse(f.Element("Weight").Value)
            });
    

    【讨论】:

    • 虽然这行得通,但lazyberezovsky 的答案更适合我,谢谢。
    • @Jobo “对我更好”是什么意思。只是感兴趣。
    • 有了你的解决方案,我最终会在我的实际查询之外得到大量的IEnumerable&lt;T&gt;s。我的实际 XML 有大约 10 种 id-referenced 标记类型,并且通过接受的解决方案,我能够编写带有嵌套查询的类似 sql 的查询,这看起来“更漂亮”并且对我来说更容易理解。
    • @Jobo IEnumerable-s用于简化理解。在 OP 中,您不使用 "sql-like" 查询,因此我像您一样使用扩展方法语法。附言由于您没有描述完整的XML,在某些情况下lazyberezovsky's 解决方案将不起作用。无论如何,祝你好运!
    • 我更喜欢查询语法,这就是我所说的“类似 sql”的意思。您的解决方案使用方法语法。我的问题是用查询语法写的。在我看来,如果您有很多嵌套的选择和连接等,查询语法将更具可读性。
    猜你喜欢
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    相关资源
    最近更新 更多