2016-07-31 10 views
1

Wie Frage Staaten. Ich habe ein XML-Dokument (unten) und ich muss X_ScalarWebApi_DeviceInfo, die Namespace Urn definiert: Schemas-Sony-Com: AV. Leider führt dies zu einem Fehler: {System.NullReferenceException: Object reference not set to an instance of an object. Ich bin hauptsächlich am ServiceList-Element interessiert, aber es funktioniert nicht so gut. Plattform - Windows 10 Mobil. Irgendwelche Ideen?XDocument get-Element, das seinen eigenen Namespace definiert

<?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> 

Ah, der Code:

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 Nun, beide Lösungen waren in Ordnung, so dass ich upvoting ein und Kennzeichnung als die andere Antwort: P Es erwähnt wurde dass die Lösung, die nur einen 'lokalen Namen' verwendet, zu falsch positiven Suchergebnissen führen könnte, also verwende ich die erste, um sicher zu sein. Danke für die Hilfe!

+0

Wo ist der Code, der den Fehler erzeugt? –

+0

Ich habe vergessen, zu ad ,, jetzt ist es in;) Wie Sie sehen können, habe ich viele Optionen ausprobiert, die ich im Internet sah –

+0

Ihre 'xDoc' haben nur ein Kindelement' ', also rufe '.Element (av +" X_ScalarWebAPI_DeviceInfo ")' return 'null'. – PetSerAl

Antwort

2

Element gibt nur Elemente direkt unterhalb des aktuellen Knotens zurück. Sie müssen die den gesamten Pfad angeben (beachten Sie, es gibt mehrere Namespaces):

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

Sind Sie sicher, über ns + "Gerät"? Gerät ist als definiert und hat keinen Namespace, also ist es in Ordnung, es in Element() -Aufruf hinzuzufügen? Ich werde es heute nicht überprüfen können, aber ich werde es ebenso wie die andere Lösung überprüfen. –

+2

Ja, Namespaces werden vererbt. Probier es einfach. –

+0

Was passiert also, wenn zwei Namespaces vorhanden sind? Wird es angehängt/überschrieben? Ich sehe, dass Sie nur den zweiten Namespace für Nachkommenknoten verwenden, für die unterschiedliche Xmlns definiert sind. –

1

Verwenden von 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; 
+0

Vorsicht, warum? Ich mag diese Lösung, es ist irgendwie ... klar. Und es wäre am besten anzunehmen, dass wir die genaue Struktur des XML nicht kennen, aber wir können sicher sein, dass es ein Element namens uv: X_ScalarWebApi_DeviceInfo und dessen Struktur (nur Nachkommen davon) gibt. –

+0

Gut gearbeitet, danke :) –

0

Das Problem ist in der Tat das oder die Elemente Methoden nur die direkten untergeordneten Elemente suchen. Du kannst mit Decendants() arbeiten, aber du erhältst eine Sammlung, also musst du First (Ausdruck) zu einem einzelnen machen.

Aber im Ausdruck können Sie .Name.LocalName verwenden, um die gesamte Namespace-Sache zu überspringen und nur nach dem Namen des Elements zu suchen.

Für diese Frage:

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