简体   繁体   English

Linq to XML查询分析

[英]Linq to XML query analyz

This query does work but I am not sure it is proper way to write this kind of query. 该查询确实有效,但是我不确定这是编写这种查询的正确方法。 I feel it is using too many Descendants and Parent. 我觉得它使用了太多的后代和父母。

Is there a better way to write this query? 有没有更好的方法来编写此查询?

There can be more than one catalog in XML. XML可以有多个目录。

static IEnumerable<Parts> GetAllParts(XDocument doc, string catalog, string groupId, string subGroupId)
    {
        var parts = (from p in doc.Descendants("ROOT").Descendants("CATALOG").Descendants("GROUP").Descendants("SUBGROUP").Descendants("BOM").Descendants("PARTS")
                     where (string)p.Parent.Parent.Parent.Parent.Element("IDENT").Value == catalog
                            && p.Parent.Parent.Parent.Element("IDENT").Value == groupId
                            && p.Parent.Parent.Element("IDENT").Value == subGroupId

                     select new Parts
                     {
                         ObjectId = int.Parse(p.Attribute("OBJECTID").Value),
                         Ident = p.Element("IDENT").Value,
                         List = p.Element("LIST").Value,
                         Descr = p.Element("DESC").Value
                     });


        return parts;

    }
}

public class Parts
{
    public int ObjectId { get; set;}
    public string Descr { get; set; }
    public string Ident { get; set;  }
    public string List { get; set; }
}

Update: XML added. 更新:添加了XML。

<ROOT>
    <CATALOG>
        <OBJECT_ID>001</OBJECT_ID>
        <OBJECT_IDENT>X001</OBJECT_IDENT>
        <GROUP>
            <OBJECT_ID>1001</OBJECT_ID>
            <OBJECT_IDENT>01</OBJECT_IDENT>
            <NAME>HOUSING</NAME>

            <SUBGROUP>              
                <OBJECT_ID>5001</OBJECT_ID>
                <OBJECT_IDENT>01.05</OBJECT_IDENT>
                <NAME>DESIGN GROUP 1</NAME>
                <BOM>
                    <OBJECT_ID>6001</OBJECT_ID>
                    <OBJECT_IDENT>010471</OBJECT_IDENT>
                    <PARTS>
                        <OBJECT_ID>2316673</OBJECT_ID>
                        <OBJECT_IDENT>A002010660</OBJECT_IDENT>
                        <DESC>SHORT BLOCK</DESC>
                        <NOTES>
                            <ROW>
                                <NOTES>Note 1</NOTES>
                                <BOM>010471</BOM>
                                <POS>1</POS>
                            </ROW>
                            <ROW>
                                <NOTES>Note 2</NOTES>
                                <BOM>010471</BOM>
                                <POS>2</POS>
                            </ROW>
                        </NOTES>
                    </PARTS>
                    <PARTS>
                    </PARTS>
                    <PARTS>
                    </PARTS>
                </BOM>
            </SUBGROUP>

            <SUBGROUP>              
            </SUBGROUP>
            <SUBGROUP>              
            </SUBGROUP>

        </GROUP>

        <GROUP>
        </GROUP>

    </CATALOG>
</ROOT>

Some suggestions regarding your question (I hope you'll improve your future posts) : 有关您的问题的一些建议(希望您以后的帖子会有所改善):

  1. Your code and the XML posted doesn't work. 您的代码和发布的XML不起作用。 For instance, the XML has <OBJECT_IDENT> element, but your LINQ has IDENT . 例如,XML具有<OBJECT_IDENT>元素,但您的LINQ具有IDENT Please craft it carefully and make sure it does work to avoid confusion. 请仔细制作,并确保它确实有效,以免造成混淆。

  2. Please put some effort in explaining the problem and giving clarification. 请付出一些努力来解释问题并进行澄清。 "I am retrieving Parts data as function name says" is not clear enough as simply getting <Parts> elements doesn't need filtering but your LINQ has where .... clause. “我正在按照函数名称的说明来获取零件数据”还不够清楚,因为仅获取<Parts>元素不需要过滤, 但是您的LINQ具有where ....子句。

  3. This question seems to suits better in https://codereview.stackexchange.com/ 这个问题似乎更适合https://codereview.stackexchange.com/

And here is some suggestions regarding your code : 以下是有关您的代码的一些建议:

  1. Use .Elements() to get direct child of current node as opposed to Descendants() which get all descendat nodes. 使用.Elements()获取当前节点的直接子节点,而使用Descendants()则获取所有后代节点。

  2. You can use Elements().Where() to filter the element so you can avoid traversing Parent s 您可以使用Elements().Where()来过滤元素,从而避免遍历Parent

  3. You can cast XElement to string / int to avoid exception in case such element not found 您可以将XElementstring / int以避免异常(如果找不到此类元素)

Example code snippet : 示例代码段:

var parts = (from p in doc.Root
              .Elements("CATALOG").Where(o => catalog == (string)o.Element("OBJECT_IDENT"))
              .Elements("GROUP").Where(o => groupId == (string)o.Element("OBJECT_IDENT"))
              .Elements("SUBGROUP").Where(o => subGroupId == (string)o.Element("OBJECT_IDENT"))
              .Elements("BOM")
              .Elements("PARTS")
             select new Parts
             {
                 ObjectId = (int)p.Element("OBJECT_ID"),
                 Ident = (string)p.Element("OBJECT_IDENT"),
                 List = (int)p.Element("LIST"),
                 Descr = (string)p.Element("DESC")
             });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM