使用LINQ to XML查询元素时出错

时间:2016-04-21 15:37:29

标签: c# xml linq

这是我所拥有的XML文件的一小部分。(见下文)。

我能够阅读我需要的内容,例如我可以获得类型消息等,但是在其中一个 PreflightResultEntry section有一组名为Var的元素我需要&#34; <Var name="NumPages">8</Var>&#34;

 --     
 <PreflightResultEntry type="GeneralDocInfo">
    <PreflightResultEntryMessage xml:lang="en-US">
        <Message>457834a.pdf </Message>
        <StringContext>
            <BaseString>%FileInfo%</BaseString>
            <Const name="Category">GeneralDocInfo</Const>
            <Const name="ActionID">-1</Const>
            <Instance>
                <Var name="FileInfo">
                    <Var name="DIPath">/V/PitStop/Testing/Mike/Processed Docs on Success/457834a.pdf</Var>
                    <Var name="CreationDate">D:20120724153648-05'00'</Var>
                    <Var name="ModDate">D:20120725134534-04'00'</Var>
                    <Var name="Producer">Adobe PDF Library 10.0</Var>
                    <Var name="Creator">Acrobat PDFMaker 10.1 for Word</Var>
                    <Var name="Author">DOL Comments</Var>
                    <Var name="Title"/>
                    <Var name="Subject"/>
                    <Var name="Keywords"/>
                    <Var name="Trapped">1</Var>
                    <Var name="NumPages">8</Var>
                    <Var name="Major">1</Var>
                    <Var name="Minor">5</Var>
                    <Var name="WasRepairedOnOpen">0</Var>
                    <Var name="IsLinearized">0</Var>
                    <Var name="ContainsThumbnails">0</Var>
                    <Var name="LeftToRightReading">1</Var>
                    <Var name="ContainsJobTicket">0</Var>
                    <Var name="EncryptionType">1</Var>
                    <Var name="Permissions">-1</Var>
                    <Var name="PrinergyTraps">3</Var>
                </Var>
                <Location page="-1"/>
            </Instance>
        </StringContext>
    </PreflightResultEntryMessage>
</PreflightResultEntry>
      ---

这里我得到的消息和类型

  List<PitStopMessage> messages = XDocument.Load(file)
      .Descendants("PreflightResultEntryMessage")
      .Where(x => x.Parent != null )
      .Select(x => new PitStopMessage()
      {
          message = x.Element("Message").Value,
          type = x.Parent.Attribute("type").Value,
          xmllevel = x.Parent.Attribute("level") != null ? x.Parent.Attribute("level").Value : String.Empty,
          link = 0
      }).ToList();

只有在元素 PreflightResultEntry

中退出时,才需要对元素var进行新查询

这里我到目前为止,但它给了我一个错误&#34;对象引用未设置为对象的实例。&#34;这说明了我所寻找的(元素)不存在。

 List<PitStopPages> messages = XDocument.Load(file)
     .Descendants("PreflightResultEntryMessage")
     .Where(x => x.Parent != null && x.Parent.Attribute("type").Value == "GeneralDocInfo" && x.Parent.Element("Var").Value == "NumPages")
     .Select(x => new PitStopPages()
     {
         Pages = x.Parent.Attribute("name").Value
     }).ToList();

3 个答案:

答案 0 :(得分:0)

我建议使用XPath来选择所需的节点。您可以使用方法XPathSelectElements并传入XPath。如果您只需要选择一个节点,则可以使用XPathSelectElement(不用&#39; s&#39;)代替。

在您的情况下,我认为XPath应该是:/PreflightResultEntry//Var[@name='NumPages']

您可以测试XPath here

答案 1 :(得分:0)

让我扩展一下@AnhTriet的建议,

var xml = new XmlDocument();

xml.LoadXml(str);  // suppose that str string contains your xml

var xnList = xml.SelectNodes("/PreflightResultEntry//Var[@name='NumPages']");

foreach (XmlNode xn in xnList)
{
    Console.WriteLine(xn.InnerText); //this should print the 8
}

.NET Fiddle

为了能够使用XPathSelectElement方法,您需要先使用XDocument类加载xml

所以,它会是这样的:

var xml = XDocument.Load(file);

XmlNode node = xml.XPathSelectElement("/PreflightResultEntry//Var[@name='NumPages']");

Console.WriteLine(node.InnerText);

答案 2 :(得分:0)

如果您在逻辑上阅读了查询,则可能会发现错误。

您的查询正在尝试查找:

  • 名为PreflightResultEntryMessage
  • 的元素
  • 其父级的type属性为GeneralDocInfo
  • 其父元素的第一个名为Var的子元素的值为NumPages
  • 获取父元素的name属性值

问题是最后两部分。在所有情况下Parent都是PreflightResultEntry元素。 PreflightResultEntry没有任何子Var元素,没有Var元素具有 NumPagesPreflightResultEntry没有name 1}}属性。其中任何一个都会导致空引用异常(您看到的异常)。

最好从上到下处理这个问题,而不是找到一个元素,然后回头查看它的父元素。所以:

  • 找到名为PreflightResultEntrytype属性为GeneralDocInfo
  • 的元素
  • 获取后代Var元素的name属性为NumPages

所以:

var numPages = (int)XDocument.Load(file)
        .Descendants("PreflightResultEntry")
        .Where(x => (string) x.Attribute("type") == "GeneralDocInfo")
        .Descendants("Var")
        .Single(x => (string) x.Attribute("name") == "NumPages");

有关正常工作的演示,请参阅this fiddle