【问题标题】:XDocument get element that defines it's own namespaceXDocument 获取定义它自己的命名空间的元素
【发布时间】:2016-07-31 18:25:02
【问题描述】:

如问题所述。我有一个 xml 文档(如下),我需要获取定义命名空间 urn:schemas-sony-com:av 的 X_ScalarWebApi_DeviceInfo。不幸的是,它会导致错误:{System.NullReferenceException: Object reference not set to an instance of an object。我主要对 ServiceList 元素感兴趣,但效果不佳。平台 - Windows 10 移动版。 有什么想法吗?

<?xml version="1.0"?>
    <root xmlns="urn:schemas-upnp-org:device-1-0">    
        <specVersion>
            <major>1</major>
            <minor>0</minor>
        </specVersion>    
        <device>
            <deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>
            <friendlyName>ILCE-6000</friendlyName>
            <manufacturer>Sony Corporation</manufacturer>
            <manufacturerURL>http://www.sony.net/</manufacturerURL>
            <modelDescription>SonyDigitalMediaServer</modelDescription>
            <modelName>SonyImagingDevice</modelName>
            <UDN>uuid:000000001000-1010-8000-62F1894EE7BE</UDN>    
            <serviceList>
               <service>
                   <serviceType>urn:schemas-sony-com:service:ScalarWebAPI:1</serviceType>
                   <serviceId>urn:schemas-sony-com:serviceId:ScalarWebAPI</serviceId>
                   <SCPDURL/>
                   <controlURL/>
                   <eventSubURL/>
               </service>
            </serviceList>
            <av:X_ScalarWebAPI_DeviceInfo xmlns:av="urn:schemas-sony-com:av">
                <av:X_ScalarWebAPI_Version>1.0</av:X_ScalarWebAPI_Version>
                <av:X_ScalarWebAPI_ServiceList>
                    <av:X_ScalarWebAPI_Service>
                        <av:X_ScalarWebAPI_ServiceType>guide</av:X_ScalarWebAPI_ServiceType>
                        <av:X_ScalarWebAPI_ActionList_URL>http://192.168.122.1:8080/sony</av:X_ScalarWebAPI_ActionList_URL>
                        <av:X_ScalarWebAPI_AccessType/>
                    </av:X_ScalarWebAPI_Service>
                    <av:X_ScalarWebAPI_Service>
                        <av:X_ScalarWebAPI_ServiceType>accessControl</av:X_ScalarWebAPI_ServiceType>
                        <av:X_ScalarWebAPI_ActionList_URL>http://192.168.122.1:8080/sony</av:X_ScalarWebAPI_ActionList_URL>
                        <av:X_ScalarWebAPI_AccessType/>
                    </av:X_ScalarWebAPI_Service>
                    <av:X_ScalarWebAPI_Service>
                        <av:X_ScalarWebAPI_ServiceType>camera</av:X_ScalarWebAPI_ServiceType>
                        <av:X_ScalarWebAPI_ActionList_URL>http://192.168.122.1:8080/sony</av:X_ScalarWebAPI_ActionList_URL>
                        <av:X_ScalarWebAPI_AccessType/>
                    </av:X_ScalarWebAPI_Service>
                </av:X_ScalarWebAPI_ServiceList>
            </av:X_ScalarWebAPI_DeviceInfo>
        </device>
    </root>

啊,代码:

XDocument xDoc = XDocument.Parse(xml_text);
//var av = xDoc.Root.GetDefaultNamespace();//.Attribute("xmlns");//
XNamespace av = "urn:schemas-sony-com:av";
System.Diagnostics.Debug.WriteLine(av);
<XElement> api_list = (List<XElement>)xDoc.Element(av + "X_ScalarWebAPI_DeviceInfo").Elements();

==编辑== 好吧,两种解决方案都可以,所以我赞成其中一个并将另一个标记为答案:P 有人提到,仅使用“本地名称”的解决方案可能会导致误报搜索结果,所以为了安全起见,我使用第一个。感谢您的帮助!

【问题讨论】:

  • 产生错误的代码在哪里?
  • 我忘了,广告,现在它在;)你可以看到我尝试了很多我在互联网上看到的选项
  • 你的xDoc只有一个子元素&lt;root xmlns="urn:schemas-upnp-org:device-1-0"&gt;,所以调用.Element(av + "X_ScalarWebAPI_DeviceInfo")返回null
  • 在以后的问题中,尝试清理并格式化您的 xml。 Visual Studio 做得很好。某些行上的- 令人困惑。
  • 其实这是来自 VisualStudio 的 XML 可视化器的输出,所以不,它做得不好 :P 我马上格式化它

标签: c# xml windows-10-mobile


【解决方案1】:

Element 只返回当前节点正下方的元素。您需要指定整个路径(注意有多个命名空间):

XNamespace ns = "urn:schemas-upnp-org:device-1-0";
XNamespace av = "urn:schemas-sony-com:av";

var api_list = xDoc.Root.Element(ns + "device")
    .Element(av + "X_ScalarWebAPI_DeviceInfo").Elements();

【讨论】:

  • 你确定 ns + "device" 吗?设备被定义为 并且没有命名空间,那么可以在 Element() 调用中添加它吗?我今天无法检查它,但我会检查它以及其他解决方案。
  • 是的,命名空间是继承的。试试看吧。
  • 那么当有两个命名空间时会发生什么?它是附加/覆盖的吗?我可以看到您只为定义了不同 xmlns 的后代节点使用了第二个命名空间。
  • 当它们引用相同的 xmlns 时被覆盖。您还可以在任何元素上拥有多个命名空间,例如xmlns:av="...",但必须在 XML 中限定元素 (av:X_ScalarWebAPI)。
  • 但是如果需要检索元素的属性,则不应应用命名空间!
【解决方案2】:

使用 Xml Linq

XDocument doc = XDocument.Load(FILENAME);
XElement x_ScalarWebAPI_DeviceInfo = doc.Descendants().Where(x => x.Name.LocalName == "X_ScalarWebAPI_DeviceInfo").FirstOrDefault();
XNamespace ns = x_ScalarWebAPI_DeviceInfo.Name.Namespace;

【讨论】:

  • 想详细说明为什么?我喜欢这个解决方案,它有点……清楚。最好假设我们不知道 XML 的确切结构,但我们可以确定有一个名为 uv:X_ScalarWebApi_DeviceInfo 的元素及其结构(仅它的后代)。
【解决方案3】:

问题确实是 Element 或 Elements 方法只搜索直接子元素。你可以使用 Decendants() 但你会得到一个集合,所以你必须做 First(expression) 来处理一个。

但在表达式中,您可以使用 .Name.LocalName 跳过整个命名空间,只查找元素的名称。

对于这个问题:

XDocument xDoc = XDocument.Parse(xml_text);
XElement x_ScalarWebAPI_DeviceInfo = doc.Descendants().First(x.Name.LocalName == "X_ScalarWebAPI_DeviceInfo");

【讨论】:

    猜你喜欢
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 2010-11-16
    • 2014-09-23
    • 2013-10-28
    • 2011-03-01
    相关资源
    最近更新 更多