.net Linq到XML获取具有名称空间的元素

.net Linq到XML获取具有名称空间的元素,.net,linq-to-xml,.net,Linq To Xml,我正在使用LINQtoXML来搜索元素 var doc = XDocument.Load(reader); var ns = doc.Root.Attribute("xmlns").Value; var result = (from u in doc.Descendants(XName.Get("MyElement", ns)) 每当我试图在xml中查找元素时,我需要放弃使用XName.get。如何将默认名称空间

我正在使用LINQtoXML来搜索元素

 var doc = XDocument.Load(reader);
                    var ns = doc.Root.Attribute("xmlns").Value;
                    var result = (from u in doc.Descendants(XName.Get("MyElement", ns))
每当我试图在xml中查找元素时,我需要放弃使用XName.get。如何将默认名称空间设置为XDocument,以便它在搜索时不会遇到麻烦

问候。

您不能:

doc = XDocument.Load(reader);
var ns = doc.Root.Attribute("xmlns").Value;
var result = from u in doc.Descendants.Elements(ns+"MyElement").Select(c=>c.Value);
每当我试图在xml中查找元素时,我需要放弃使用XName.get。如何将默认名称空间设置为XDocument,以便它在搜索时不会遇到麻烦

你不能,但还有两个选择:

  • 使用
    +(XNamespace,string)
    运算符:

    doc.Descendants(ns + "MyElement")
    
  • 只需创建一次
    XName
    值,然后在查询中引用它们,例如

    XName myElementName = ns + "MyElement";
    ...
    doc.Descendants(myElementName);
    

理想情况下,无论如何都不会动态创建名称空间-您不知道应该查找的名称空间吗?如果这样做,您可以使用适当的
XName
值创建私有静态只读字段。

如果您确实想这样做,这里有一种忽略默认名称空间的方法:

        XDocument doc;
        using (XmlTextReader xr = new XmlTextReader("input.xml"))
        {
            xr.Namespaces = false;
            doc = XDocument.Load(xr);
        }
        foreach (XElement bar in doc.Descendants("bar"))

但我建议接受XML中名称空间的存在和重要性,并使用LINQtoXML提供的XName和XNamespace对象来处理它们

您还可以使用LocalName,它使LINQ丑陋,但可以完成任务。(在本例中,从MSBuild项目文件获取属性)

我喜欢这样做的一点是,它将XML保留为其原始形式,但它向其他人暗示正在发生一些有趣的事情。在LINQ表达式中添加“LocalName”有点像是一种自我记录的黑客行为


如果代码分离,关闭XmlTextReader中的名称空间很容易被忽略。

创建扩展方法:

        public static XElement ElementInCurrentNamespace(this XElement element, string elementName)
        {
            return element
                .Element(element.Name.Namespace.GetName(elementName));
        }

        public static IEnumerable<XElement> ElementsInCurrentNamespace(this XElement element, string elementName)
        {
            return element
                .Elements(element.Name.Namespace.GetName(elementName));
        }
公共静态XElement元素InCurrentNamespace(此XElement元素,string elementName)
{
返回元素
.Element(Element.Name.Namespace.GetName(elementName));
}
公共静态IEnumerable元素SinCurrentNamespace(此XElement元素,string elementName)
{
返回元素
.Elements(element.Name.Namespace.GetName(elementName));
}
  • 第一次使用命名空间访问元素时,请使用
    .element
    .Elements
    方法和命名空间,例如
    element.element(namespace.GetName(“foo”)
  • 然后(只要子元素具有相同的名称空间)使用上述扩展方法

    • 这是一篇老文章,但我的想法如下:

      Elements.xml根元素包含名称空间属性。下面的代码忽略名称空间

      XDocument doc = XDocument.Load("Elements.xml");
      
                  if (doc.Root != null)
                      foreach (XElement xElement in doc.Root.Elements())
                      {
                          Console.WriteLine(xElement);
                      }
      

      同样,这将需要连接ns,并使代码有点模糊。我们不能避免ns吗?您的查询应该如下:var result=from u in doc.subjections()。Elements(ns+“MyElement”)选择u;因此,没有办法说这个节点中的所有元素都属于这个名称空间,这将允许我只按名称搜索元素,对吗?@Shoaib Shaikh:您只按
      XName
      搜索,而不是按字符串搜索。当您通过从字符串转换创建
      XName
      时,将创建一个没有命名空间的
      XName
      。您可以先从xml文本中删除命名空间,然后再将其作为XDocument使用。您可以在搜索中使用element.Name.LocalName。@ImaDirtyTroll:但为什么不只是指定命名空间呢?(这也是我在使用MSBuild时会做的…)在大多数情况下,您真的不希望最终得到的元素位于错误的命名空间中,但恰好位于文档中。是的,我同意命名空间的重要性,但在我的情况下,我的xml文档元素属于我已知的单个命名空间。所以我真的不需要在搜索元素时一遍又一遍地传递它。
      XDocument doc = XDocument.Load("Elements.xml");
      
                  if (doc.Root != null)
                      foreach (XElement xElement in doc.Root.Elements())
                      {
                          Console.WriteLine(xElement);
                      }