web-dev-qa-db-fra.com

XDocument contenant des espaces de noms

J'ai le XML suivant que j'essaie d'interroger avec XDocument:

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

L'exécution du code suivant renvoie null pour xEl1 sauf lorsque je supprime manuellement les espaces de noms:

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;

Comment écrivez-vous le code pour extraire le Guid dans XDocument?

43
Gineer

Essayez ça, ça marche pour moi

    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;

Vous devez utiliser Namespaces .

Source complète pour le procès

        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();
        }
60
Binary Worrier

Anthony a adressé le bit d'espace de noms - et XAttribute a une conversion explicite en GUID, donc cela devrait fonctionner:

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

Notez comment les espaces de noms sont pas hérités pour les attributs.

Utiliser une seule instruction comme je l'ai fait ici peut parfois rendre la vie plus simple, mais cela le fait rend le débogage plus difficile car vous ne voyez pas les valeurs intermédiaires. Modifiez selon le goût :)

22
Jon Skeet

Utilisez des objets Namespace dans votre requête pour les balises "xmlns =" ​​données dans les éléments que vous souhaitez interroger. N'a pas été testé, mais quelque chose comme ça devrait fonctionner

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");
2
Anthony Pegram