【问题标题】://@attrib vs //name/@attrib in C#//@attrib 与 //name/@attrib 在 C# 中
【发布时间】:2012-04-21 12:07:56
【问题描述】:

在下面的 XML 上,我使用 XmlDocumentSelectSingleNode 来提取结果值。

evtASxml.SelectSingleNode(@"//@value").Value

返回第一个“值”的值。

evtASxml.SelectSingleNode(@"//Result/@value").Value

引发空异常。

有人能解释一下发生了什么吗?

 <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
 <System>
  <Provider Name="Microsoft-Windows-CAPI2" Guid="{f00f00-f00-f00f00-f00-f00f00f00}" /> 
  <EventID>30</EventID> 
  <Version>0</Version> 
  <Level>2</Level> 
  <Task>30</Task> 
  <Opcode>0</Opcode> 
  <Keywords>0x4000000000000001</Keywords> 
  <TimeCreated SystemTime="2012-04-08T23:43:37.573242200Z" /> 
  <EventRecordID>4828</EventRecordID> 
  <Correlation ActivityID="{f00f00-f00-f00-f00-f00f00f00f00}" /> 
  <Execution ProcessID="7512" ThreadID="3220" /> 
  <Channel>Microsoft-Windows-CAPI2/Operational</Channel> 
  <Computer>Matt-Seven</Computer> 
  <Security UserID="S-f00-f00-f00-f00f00f00-f00f00f00-f00f00f00-f00f00" /> 
  </System>
 <UserData>
 <CertVerifyCertificateChainPolicy>
  <Policy type="CERT_CHAIN_POLICY_SSL" constant="4" /> 
  <Certificate fileRef="f00f00f00f00f00f00f00f00f00f00f00.cer" subjectName="www.example.com" /> 
  <CertificateChain chainRef="{f00f00-f00-f00-f00-f00f00f00f00}" /> 
  <Flags value="0" /> 
 <SSLAdditionalPolicyInfo authType="server" serverName="example.com">
  <IgnoreFlags value="0" /> 
  </SSLAdditionalPolicyInfo>
  <Status chainIndex="0" elementIndex="0" /> 
  <EventAuxInfo ProcessName="iexplore.exe" /> 
  <CorrelationAuxInfo TaskId="{f00f00-f00-f00-f00-f00f00f00f00}" SeqNumber="4" /> 
  <Result value="800B010F">The certificate's CN name does not match the passed value.</Result> 
  </CertVerifyCertificateChainPolicy>
  </UserData>
  </Event>

我的事件日志中的数值替换为 f00。

【问题讨论】:

  • 我相信现在它与命名空间影响 XPATH 查询的方式有关。 msdn.microsoft.com/en-us/library/ms950779.aspx
  • 好的,添加 XmlNamespaceManager ns = new XmlNamespaceManager(evtASxml.NameTable); ns.AddNamespace("foo", "http://schemas.microsoft.com/win/2004/08/events/event"); 并使用 evtASxml.SelectSingleNode(@"//foo:Result/@value",ns).Value 可以正常工作。命名空间看起来很不优雅。

标签: c# xpath xmldocument selectsinglenode


【解决方案1】:

只是猜测,但我认为你想要//*[@value],而不是//@value

【讨论】:

  • Console.WriteLine(evtASxml.SelectSingleNode(@"//@serverName").Value 对我来说工作得很好,那里只有一个具有该名称的属性。
  • 你在那里建造的很棒的工具 Cheeso!我一定用过一百万次 XPath Visualizer。哦!还有.NET Zip :D
  • 有没有办法让我的代码像 xpath 可视化工具一样使用默认的 ns?
  • 我不知道一个好方法,马特。该工具的做法是一种血腥的黑客攻击——它实际上解析字符串并在它认为合适的每个地方插入命名空间前缀。但是,它并不完美,并且在某些极端情况下确实会中断。但是,如果您的 xpath 不会很复杂,那么这种快速/肮脏的方法可能就是您想要的。如果是这样,请参阅 xpathvisualizer.svn.codeplex.com/svn/XPathVisualizer/Tool/… 并查找 FixupXpathExpressionWithDefaultNamespace 方法。
  • 在我的 xpath 语句中添加前缀并不算太糟糕,因为我的应用程序只需要少数几个。我在网上发现了很多关于 XML 命名空间的抱怨,知道我不是唯一一个有问题的人,这让我感觉好多了。
【解决方案2】:

此问题的原因是 XML 文档位于默认命名空间中

在默认命名空间中按名称选择元素是 XPath 中最常见的常见问题。

Xpath 将任何无前缀的元素名称视为属于“无命名空间”。在您的情况下,“无命名空间”中不存在 Result 元素(所有元素都在“http://schemas.microsoft.com/win/2004/08/events/event”命名空间中),因此没有节点已选中。

在 C# 中,建议您提供 XmlNamespaceManager 作为SelectSingleNode() 的第二个参数——只需使用the appropriate overload

用途:

evtASxml.SelectSingleNode(@"//x:Result/@value", yourXmlNamespaceManager).Value 

"x" 与“http://schemas.microsoft.com/win/2004/08/events/event”命名空间的关联已使用 AddNamespace() 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-25
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多