【问题标题】:Use Linq to Xml with Xml namespaces使用带有 Xml 命名空间的 Linq to Xml
【发布时间】:2011-01-21 09:01:44
【问题描述】:

我有这个代码:

/*string theXml =
@"<Response xmlns=""http://myvalue.com""><Result xmlns:a=""http://schemas.datacontract.org/2004/07/My.Namespace"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><a:TheBool>true</a:TheBool><a:TheId>1</a:TheId></Result></Response>";*/

string theXml = @"<Response><Result><TheBool>true</TheBool><TheId>1</TheId></Result></Response>";

XDocument xmlElements = XDocument.Parse(theXml);

var elements = from data in xmlElements.Descendants("Result")
               select new {
                            TheBool = (bool)data.Element("TheBool"),
                            TheId = (int)data.Element("TheId"),
                          };

foreach (var element in elements)
{
    Console.WriteLine(element.TheBool);
    Console.WriteLine(element.TheId);
}

当我为 theXml 使用第一个值时,结果为 null,而使用第二个值时,我有很好的值...

如何使用带有 xmlns 值的 Linq to Xml ?

【问题讨论】:

    标签: c# linq-to-xml xml-namespaces


    【解决方案1】:

    DescendantsElement 这样的LINQ to XML 方法将XName 作为参数。从stringXName 的转换会自动为您发生。您可以通过在DescendantsElement 调用中的字符串之前添加XNamespace 来解决此问题。请注意,因为您有 2 个不同的命名空间在工作。

    string theXml = @"true1"; //string theXml = @"true1"; XDocument xmlElements = XDocument.Parse( theXml ); XNamespace ns = "http://myvalue.com"; XNamespace nsa = "http://schemas.datacontract.org/2004/07/My.Namespace"; var elements = from data in xmlElements.Descendants( ns + "Result" ) select new { TheBool = (bool) data.Element( nsa + "TheBool" ), TheId = (int) data.Element( nsa + "TheId" ), }; foreach ( var element in elements ) { Console.WriteLine( element.TheBool ); Console.WriteLine( element.TheId ); }

    注意Descendants 中的ns 和Elements 中的nsa

    【讨论】:

    • xmlElements.Descendants(xmlElements.Root.GetDefaultNamespace() + "Result") 也可以工作...
    • .GetDefaultNamespace() 的另一个对应物是 .GetNamespaceOfPrefix(),对于像 &lt;foo:Result xmlsns:foo="https://example.com"/&gt; 这样的 xml 很有用
    【解决方案2】:

    您可以将带有命名空间的XName 传递给Descendants()Element()。当您将字符串传递给 Descendants() 时,它会隐式转换为没有命名空间的 XName。

    要在命名空间中创建 XName,您需要创建 XNamespace 并将其连接到元素 local-name(字符串)。

    XNamespace ns = "http://myvalue.com";
    XNamespace nsa = "http://schemas.datacontract.org/2004/07/My.Namespace";
    
    var elements = from data in xmlElements.Descendants( ns + "Result")
                       select new
                                  {
                                      TheBool = (bool)data.Element( nsa + "TheBool"),
                                      TheId = (int)data.Element( nsa + "TheId"),
                                  };
    

    还有一种通过字符串隐式转换来创建带有命名空间的 XName 的简写形式。

    var elements = from data in xmlElements.Descendants("{http://myvalue.com}Result")
                       select new
                                  {
                                      TheBool = (bool)data.Element("{http://schemas.datacontract.org/2004/07/My.Namespace}TheBool"),
                                      TheId = (int)data.Element("{http://schemas.datacontract.org/2004/07/My.Namespace}TheId"),
                                  };
    

    或者,您可以查询 XElement.Name.LocalName

    var elements = from data in xmlElements.Descendants()
                       where data.Name.LocalName == "Result"
    

    【讨论】:

    • LocalName 在我的智能感知中不存在
    • 从 + 运算符到 xname 的转换是灰熊的、可怕的和完全可憎的。 MS在想什么?大概它在引擎盖下使用了 Expression> - 让我感觉不舒服。
    【解决方案3】:

    我在 XML 文档的顶部列出了几个名称空间,我并不真正关心哪些元素来自哪个名称空间。我只想按名称获取元素。我写了这个扩展方法。

        /// <summary>
        /// A list of XElement descendent elements with the supplied local name (ignoring any namespace), or null if the element is not found.
        /// </summary>
        public static IEnumerable<XElement> FindDescendants(this XElement likeThis, string elementName) {
            var result = likeThis.Descendants().Where(ele=>ele.Name.LocalName==elementName);
            return result;
        }
    

    【讨论】:

    • 这对我有用,谢谢。
    【解决方案4】:

    我发现以下代码可以很好地用于在 VB.NET 中读取带有命名空间的属性:

    MyXElement.Attribute(MyXElement.GetNamespaceOfPrefix("YOUR_NAMESPACE_HERE") + "YOUR_ATTRIB_NAME")
    

    希望这对以后的人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-06
      • 1970-01-01
      • 1970-01-01
      • 2014-02-07
      • 1970-01-01
      相关资源
      最近更新 更多