【问题标题】:XDocument containing namespaces包含命名空间的 XDocument
【发布时间】:2011-03-01 05:37:09
【问题描述】:

我尝试使用 XDocument 查询以下 XML:

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

执行以下代码会为 xEl1 返回 null 除非我手动删除命名空间

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;

如何编写代码来提取 XDocument 中的 Guid?

【问题讨论】:

    标签: c# xml linq linq-to-xml xml-namespaces


    【解决方案1】:

    试试这个,对我有用

        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;
    

    您需要使用Namespaces

    完整的试用源码

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

    【讨论】:

    • 这对我来说完全没有任何意义,直到我意识到他们正在覆盖 XNamespacestring 的 + 运算符。呸呸呸呸。
    • 如果您想避免“+”运算符重载,可以从本地名称和命名空间显式创建 XName,如下所示:XName.Get("System",nsSys.NamespaceName)
    【解决方案2】:

    Anthony 解决了命名空间位 - 并且 XAttribute 已显式转换为 GUID,所以这应该可以工作:

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

    注意命名空间是如何为属性继承的。

    像我在这里所做的那样使用单个语句有时可以使生活变得更简单,但它确实使调试变得更加困难,因为您看不到中间值。根据口味修改:)

    【讨论】:

    【解决方案3】:

    在您的查询中使用 XNamespace 对象作为您要查询的元素中给定的“xmnls=”标签。尚未测试,但这样的东西应该可以工作

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

    【讨论】:

      猜你喜欢
      • 2010-11-16
      • 2014-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      • 2015-11-15
      相关资源
      最近更新 更多