XDocument获取定义它自己的命名空间的元素

时间:2016-07-31 18:25:02

标签: c# xml windows-10-mobile

正如问题所述。我有一个xml文档(下面),我需要获得定义命名空间urn的X_ScalarWebApi_DeviceInfo:schemas-sony-com:av。不幸的是,它会导致错误:{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();

== EDIT == 好吧,两种解决方案都没问题,所以我正在推测一个并标记为另一个答案:P 有人提到仅使用“本地名称”的解决方案可能会导致误报搜索结果,所以为了安全起见,我正在使用第一个。谢谢你的帮助!

3 个答案:

答案 0 :(得分:3)

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();

答案 1 :(得分:1)

使用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;

答案 2 :(得分:0)

问题确实是Element或Elements方法只搜索直接子元素。您可以使用Decendants(),但是您将获得一个集合,因此您必须执行First(表达式)才能获得单个集合。

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

对于这个问题:

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