代码之家  ›  专栏  ›  技术社区  ›  bouvard

通过Linq到XML进行查询时,如何处理任意名称空间?

  •  19
  • bouvard  · 技术社区  · 17 年前

    我有一个项目,我正在使用一些特别难看的“实时”HTML,并使用HTML敏捷包将其强制转换为正式的XML DOM。我想能够做的是,然后使用LINQtoXML对此进行查询,这样我就可以从中提取出所需的信息。我正在使用描述的方法 here

    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    

    尝试从此文档进行查询时,namespace属性似乎阻止我执行以下操作:

    var x = xDoc.Descendants("div");
    // returns null
    

    显然,对于那些“div”标记,只有LocalName是“div”,但正确的标记名是名称空间加上“div”。我尝试过对XML名称空间问题进行一些研究,似乎可以通过以下方式查询来绕过名称空间:

    var x = 
        (from x in xDoc.Descendants()
         where x.Name.LocalName == "div"
         select x);
    // works
    

    然而,这似乎是一个相当粗糙的解决方案,并没有正确地解决名称空间问题。据我所知,一个适当的XML文档可以包含多个名称空间,因此正确的处理方法应该是解析出我正在查询的名称空间。还有其他人必须这样做吗?我是不是正朝着复杂的方向前进?我知道我可以通过坚持使用HtmlDocument和XPath查询来避免这一切,但如果可能的话,我更愿意坚持使用我所知道的(Linq),我也更愿意知道,我并不是在为以后的命名空间相关问题做准备。

    在这种情况下,处理名称空间的正确方法是什么?

    3 回复  |  直到 17 年前
        1
  •  17
  •   Mark Cidade    17 年前

    使用 LocalName 应该没问题。如果你不在乎它的名字空间,我不会认为它是一个黑客。

    var ns = "{http://www.w3.org/1999/xhtml}";
    var x  = xDoc.Root.Descendants(ns + "div");
    

    MSDN reference )

    var namespaces = (from x in xDoc.Root.DescendantsAndSelf()
                      select x.Name.Namespace).Distinct();
    

    我想你可以用它来做这件事,但它实际上是一种黑客行为:

    var x = namespaces.SelectMany(ns=>xDoc.Root.Descendants(ns+"div"));
    
        2
  •  2
  •   StriplingWarrior    14 年前

    var ns = xDoc.Root.Name.Namespace;
    var x = xDoc.Descendants(ns + "div");
    
        3
  •  -11
  •   piers7    17 年前

    我认为你的Google fu让你失望了:

    http://www.google.com.au/search?hl=en&q=linq+xml+namespaces

    推荐文章