C#:读取 XML 属性

Posted

技术标签:

【中文标题】C#:读取 XML 属性【英文标题】:C#: Read XML Attribute 【发布时间】:2012-06-06 19:14:57 【问题描述】:

使用 C#2.0 和 VIsualStudio2005

我正在尝试访问“MonitorResponseRecord”中的“DisplayName” 来自如下 XML 文件:

    <Magellan xsi:schemaLocation="http://tempuri.org/XMLSchema.xsd ..\Schema\Configuration.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
      <SchemaVersion>1.0</SchemaVersion>
          <MonitorScope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="CleanStationChemicalManifoldFeed5" xmlns="http://tempuri.org/XMLSchema.xsd">
            <PersonalSafety>
              <MonitorResponseRecord Enabled="true" DisplayName="ChemicalManifoldFeed5ControllerFault">
                <ExpressionMonitor>
                  <Expression>(ChemicalManifold.Feed5.DispenseValve = Open) and ((ChemicalManifold.Feed5.ViolatedRegion = HighProcess) or (ChemicalManifold.Feed5.ViolatedRegion = LowProcess) or (ChemicalManifold.Feed5.ViolatedRegion = Minimum))</Expression>
                  <TestInterval>0.1</TestInterval>
                  <MinimumTimeBetweenResponses>5</MinimumTimeBetweenResponses>
                </ExpressionMonitor>
                <Response>
                  <PostAlarm>
                    <AlarmName>ChemicalManifold_Feed5_ControllerFault</AlarmName>
                    <Parameter1 />
                    <Parameter2>Alarm Region = ChemicalManifold.Feed5.ViolatedRegion</Parameter2>
                    <Parameter3>RecipeName-StepName</Parameter3>
                    <Parameter4>FlowSetpoint = ChemicalManifold.Feed5.Setpoint-LPM, ActualFlow = ChemicalManifold.Feed5.FlowMeter-LPM</Parameter4>
                  </PostAlarm>
                  <ResponseEvent>
                    <TargetResource />
                    <Event>PA</Event>
                    <Reason>ChemicalSupply</Reason>
                  </ResponseEvent>
                </Response>
              </MonitorResponseRecord>
            </PersonalSafety>
            <PersonalSafety>
              <MonitorResponseRecord Enabled="true" DisplayName = "PressureValveFailure">
           ...
            ...                
             ...and soon

我目前的C#尝试如下,但是当我尝试XmlDocument.Load("");时它总是挂断

                XmlDocument doc = new XmlDocument();
                doc.Load("../UMC0009.Configuration.Root.xml");
                string attrVal = doc.SelectSingleNode("MonitorResponseRecord/@DisplayName").Value;
                

BUUUUT 不起作用:/ 有什么帮助吗?

更新:

我收到的异常如下,发生在 doc.Load("...") 行:

"Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function." System.Exception System.Xml.XPath.XPathException

【问题讨论】:

如果它在负载上“挂起”,那么它不喜欢您提供的路径。尝试完整路径! 不幸的是没有区别:( 正如@banging 所暗示的那样:如果您“挂”在Load(...) 上,那么您应该收到一个异常。请给我们一个例外! :) "需要命名空间管理器或 XsltContext。此查询具有前缀、变量或用户定义的函数。" System.Exception System.Xml.XPath.XPathException 你确定 Load() 抛出了异常吗?!因为 Load 只抛出 XmlExceptions 而抛出 XPathException 的方法(你所拥有的)是 SelectSingleNode() 方法! Adolfo 的回答似乎正是您所需要的 ;) 【参考方案1】:

您的 XPath 查询将相对于文档根目录:

doc.SelectSingleNode("MonitorResponseRecord/@DisplayName")

要使其在文档中的任何位置搜索,请使用双斜杠前缀:

doc.SelectSingleNode("//MonitorResponseRecord/@DisplayName")

如果这仍然不起作用,我会在删除两个根节点上的所有命名空间声明后尝试上面的示例。

否则,使用命名空间声明时,您可能会发现需要定义 XML 命名空间映射并在 XPath 中使用前缀,例如:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("x", "http://tempuri.org/XMLSchema.xsd");

doc.SelectSingleNode("//x:MonitorResponseRecord/@DisplayName")

【讨论】:

你的这个答案给了我一个例外:“需要命名空间管理器或 XsltContext。这个查询有一个前缀、变量或用户定义的函数。” System.Exception System.Xml.XPath .XPathException 我已经稍微更新了我的第三个 sn-p,不应该在属性上加上前缀。你试过我所说的剥离命名空间声明吗? XML文件的大小是多少?是不是因为太大而挂了? @KrisG,当您在 XPath 表达式中使用命名空间前缀时,您还需要提供一个 XmlNamespaceManager 实例(这是 DarthSheldon 评论中的异常所指出的)。请参阅SelectSingleNode doc page 上的示例以了解如何执行此操作;您可能需要相应地更新您的第三个 sn-p。 (可能,您需要再次向属性添加前缀......如果我没看错的话,DisplayName 是默认命名空间中的一个属性,就像 MonitorResponseRecord 元素一样。) 感谢 O. R. Mapper,我已经添加了命名空间映射逻辑。 谢谢 O.R. Mapper 和 KrisG 我会试试这个。 @KrisG 就 .xml 文件大小而言,它是 1.1Mb,相当大,这可能导致挂断吗?如果是这样,我该怎么做才能解决这个问题【参考方案2】:

怎么样:

    XmlDocument doc = new XmlDocument();
    doc.Load("UMC0009.Configuration.Root.xml");

    XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
    nsmgr.AddNamespace("ns", "http://tempuri.org/XMLSchema.xsd");
    string attrVal = doc.SelectSingleNode("//ns:MonitorResponseRecord/@DisplayName", nsmgr).Value;

使用命名空间管理器,指定命名空间 URI 并在 XPath 中使用它。 它对我有用。

【讨论】:

我会这样做,但我的程序一直挂在 doc.Load() 上并跳转到异常,跳过它下面的所有其他内容 @DarthSheldon:发布您在回答中遇到的异常。 将你的逻辑包装在一个 try/catch 块中,并发布你得到的异常 已经在 try/catch 块中,我收到的异常是:"需要命名空间管理器或 XsltContext。此查询具有前缀、变量或用户定义的函数。" System.Exception System.Xml.XPath.XPathException 在答案中执行我的代码时,您是否遇到了该异常?它应该照顾好...

以上是关于C#:读取 XML 属性的主要内容,如果未能解决你的问题,请参考以下文章

c# xPathDocument读取xml节点属性

C# XML 如何直接根据属性值 读取 对应的值 怎么写???

使用带有 C# 的 XmlDocument 读取 XML 数据 - 读取属性数据并拆分结果

使用 c# 在属性级别读取带有名称空间的 XML

c#如何用xelement读取xml属性

C# Linq to XML 读取多个带有属性的标签