2010-06-08 7 views
35

Ho il seguente codice XML, che sto cercando di interrogare con XDocument:XDocument contenente namespace

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent"> 
    <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system"> 
     <EventID>589828</EventID> 
     <Type>3</Type> 
     <SubType Name="Information">0</SubType> 
     <Level>8</Level> 
     <TimeCreated SystemTime="2010-06-01T09:45:15.8102117Z" /> 
     <Source Name="System.ServiceModel" /> 
     <Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" /> 
     <Execution ProcessName="w3wp" ProcessID="5012" ThreadID="5" /> 
     <Channel /> 
     <Computer>TESTSERVER3A</Computer> 
    </System> 
    <ApplicationData> 
     <TraceData> 
      <DataItem> 
       <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Information"> 
        <TraceIdentifier>http://msdn.microsoft.com/en-GB/library/System.ServiceModel.Activation.WebHostCompilation.aspx</TraceIdentifier> 
        <Description>Webhost compilation</Description> 
        <AppDomain>/LM/W3SVC/257188508/Root-1-129198591101343437</AppDomain> 
        <Source>System.ServiceModel.Activation.ServiceParser/39498779</Source> 
        <ExtendedData xmlns="http://schemas.microsoft.com/2006/08/ServiceModel/StringTraceRecord"> 
         <VirtualPath>/Service.svc</VirtualPath> 
        </ExtendedData> 
       </TraceRecord> 
      </DataItem> 
     </TraceData> 
    </ApplicationData> 
</E2ETraceEvent> 

Eseguire il seguente codice restituisce null per xEl1 tranne quando rimuovo manualmente gli spazi dei nomi:

XDocument xDoc = XDocument.Parse(CurrentString); 
XElement xEl1 = xDoc.Element("E2ETraceEvent"); 
XElement xEl2 = xEl1.Element("System"); 
XElement xEl3 = xEl2.Element("Correlation"); 
XAttribute xAtt1 = xEl3.Attribute("ActivityID"); 
String sValue = xAtt1.Value; 

Come si scrive codice per estrarre il Guid in XDocument?

risposta

51

Prova questa, funziona per me

XNamespace nsSys = "http://schemas.microsoft.com/2004/06/windows/eventlog/system"; 
    XElement xEl2 = xDoc.Element(nsSys + "System"); 
    XElement xEl3 = xEl2.Element(nsSys + "Correlation"); 
    XAttribute xAtt1 = xEl3.Attribute("ActivityID"); 
    String sValue = xAtt1.Value; 

è necessario utilizzare Namespaces.

sorgente completo per la prova

 public static void Main() 
     { 
      XElement xDoc = XElement.Parse(
      @"<E2ETraceEvent xmlns=""http://schemas.microsoft.com/2004/06/E2ETraceEvent""> 
    <System xmlns=""http://schemas.microsoft.com/2004/06/windows/eventlog/system""> 
     <EventID>589828</EventID> 
     <Type>3</Type> 
     <SubType Name=""Information"">0</SubType> 
     <Level>8</Level> 
     <TimeCreated SystemTime=""2010-06-01T09:45:15.8102117Z"" /> 
     <Source Name=""System.ServiceModel"" /> 
     <Correlation ActivityID=""{00000000-0000-0000-0000-000000000000}"" /> 
     <Execution ProcessName=""w3wp"" ProcessID=""5012"" ThreadID=""5"" /> 
     <Channel /> 
     <Computer>TESTSERVER3A</Computer> 
    </System> 
    <ApplicationData> 
     <TraceData> 
      <DataItem> 
       <TraceRecord xmlns=""http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord"" Severity=""Information""> 
        <TraceIdentifier>http://msdn.microsoft.com/en-GB/library/System.ServiceModel.Activation.WebHostCompilation.aspx</TraceIdentifier> 
        <Description>Webhost compilation</Description> 
        <AppDomain>/LM/W3SVC/257188508/Root-1-129198591101343437</AppDomain> 
        <Source>System.ServiceModel.Activation.ServiceParser/39498779</Source> 
        <ExtendedData xmlns=""http://schemas.microsoft.com/2006/08/ServiceModel/StringTraceRecord""> 
         <VirtualPath>/Service.svc</VirtualPath> 
        </ExtendedData> 
       </TraceRecord> 
      </DataItem> 
     </TraceData> 
    </ApplicationData> 
</E2ETraceEvent>"); 

      XNamespace nsSys = "http://schemas.microsoft.com/2004/06/windows/eventlog/system"; 
      XElement xEl2 = xDoc.Element(nsSys + "System"); 
      XElement xEl3 = xEl2.Element(nsSys + "Correlation"); 
      XAttribute xAtt1 = xEl3.Attribute("ActivityID"); 
      String sValue = xAtt1.Value; 

      Console.WriteLine("sValue = {0}", sValue); 

      Console.ReadKey(); 
     } 
+0

Lo spazio dei nomi è la chiave – ChrisP

+14

Questo non ha assolutamente senso per me finché non ho realizzato che stavano eseguendo l'override dell'operatore + per 'XNamespace' e' string'. Yucky yuck yuck. –

+3

Se si desidera evitare il sovraccarico dell'operatore "+", è possibile creare XName esplicitamente da un nome e uno spazio dei nomi locali come questo: 'XName.Get (" Sistema ", nsSys.NamespaceName)' – Coruscate5

1

Utilizzare gli oggetti XNamespace nella query per i tag "xmnls =" specificati negli elementi che si desidera interrogare. Non ho ancora testato, ma qualcosa di simile dovrebbe funzionare

XNamespace eventSpace = "http://schemas.microsoft.com/2004/06/E2ETraceEvent"; 
XNamespace systemSpace = "http://schemas.microsoft.com/2004/06/windows/eventlog/system"; 

XElement eventElement = document.Element(eventSpace + "E2ETraceEvent"); 
XElement systemElement = eventElement.Element(systemSpace + "System"); 
20

Anthony affrontato il bit namespace - e XAttribute ha una conversione esplicita per GUID, quindi questo dovrebbe funzionare:

XNamespace eventNs = "http://schemas.microsoft.com/2004/06/E2ETraceEvent"; 
XNamespace systemNs = "http://schemas.microsoft.com/2004/06/windows/eventlog/system"; 

Guid guid = (Guid) document.Element(eventNs + "E2ETraceEvent") 
          .Element(systemNs + "System") 
          .Element(systemNs + "Correlation") 
          .Attribute("ActivityID"); 

Si noti come spazi dei nomi sono non ereditato per attributi.

Utilizzare una singola istruzione come ho fatto qui a volte può semplificare la vita, ma è rendere più difficile il debug in quanto non è possibile visualizzare i valori intermedi. Modifica secondo il gusto :)

+0

Penso che intendi implicito conversione dell'operatore? :) –

+3

@ Mark: No, intendo esplicito. Vedi http://msdn.microsoft.com/en-us/library/bb301657(v=vs.110).aspx –