【问题标题】:Descendants within descendants in LINQ to XMLLINQ to XML 中后代中的后代
【发布时间】:2011-12-20 14:06:28
【问题描述】:

我正在努力导航到我的 XML 中的“用户”元素;我想要一组用户,这样我就可以提取用户名详细信息。我的 LINQ 查询如下,计数总是返回 0(虽然不为空)

var xApprovers = from d in doc.Root.Descendants("document_version")
                               .Elements("stages")
                               .Elements("stage")
                               .Elements("user")
                               .Elements("approver_list")
                               .Elements("approver")
                               .Elements("user")
                 where d.Element("docVersionID").Value == vId
                 select d;

我的 XML 源是:

<Root>
<document_version>
    <version_number>1</version_number>
    <version_comments></version_comments>
    <creation_date>2011-12-20 09:20:42.877</creation_date>
    <docVersionID>00002_0000000453</docVersionID>
    <pageno>-1</pageno>
    <author>
      <user>
        <userID>00002_0000000001</userID>
        <login>ACRE_ROBOT</login>
        <lastname>ROBOT</lastname>
        <firstname>ACRE</firstname>
        <email>richardtaylor@vcg-kestrel.com</email>
      </user>
    </author>
    <document_approval_cycle_code>0</document_approval_cycle_code>
    <document_approval_cycle_status>Not Started</document_approval_cycle_status>
    <stage_index>1</stage_index>
    <stages>
      <stage>
        <stage_id>00002_0000001017</stage_id>
        <name></name>
        <index>1</index>
        <conditional_approval>1</conditional_approval>
        <upon_rejection_code>0</upon_rejection_code>
        <stage_approval_cycle_code>0</stage_approval_cycle_code>
        <stage_approval_cycle_status>Not Started</stage_approval_cycle_status>
        <stage_approval_code>00001_0000000002</stage_approval_code>
        <stage_approval_status>Pending</stage_approval_status>
        <approver_list>
          <approver>
            <user>
              <userID>00002_0000000011</userID>
              <login>DEVAPP78@APPROVER.COM</login>
              <lastname>App 78</lastname>
              <firstname>Dev</firstname>
              <email>DevApp78@approver.com</email>
            </user>
            <approval_action />
          </approver>
          <approver>
            <user>
              <userID>00002_0000000010</userID>
              <login>DEVAPP77@APPROVER.COM</login>
              <lastname>App 77</lastname>
              <firstname>Dev</firstname>
              <email>DevApp77@approver.com</email>
            </user>
            <approval_action />
          </approver>
        </approver_list>
      </stage>
    </stages>
    <approvals></approvals>
</document_version>
</Root>

我做错了什么?提前致谢。

【问题讨论】:

  • 所以你需要document_version 的所有usersdocVersionID 给出,对吧?

标签: c# .net xml linq linq-to-xml


【解决方案1】:

你有两个问题,你有一个多余的 .Elements("user") 这是不必要的

您还试图将 where 子句应用于错误的元素

这是更正后的 LINQ,它以与原始文件相同的 IEnumerable 形式返回结果

  var xGood = from docVersion in doc.Root.Descendants( "document_version" )
              where docVersion.Element("docVersionID").Value == vId
              from d in docVersion.Elements( "stages" )
                                  .Elements( "stage" )
                                  .Elements( "approver_list" )
                                  .Elements( "approver" )
                                  .Elements( "user" )
              select d;

此 LINQ 和 abatishchev 之间的显着区别在于,这将支持单个 xml 文档中的多个 document_version 节点

【讨论】:

  • 谢谢你,梅里克,太完美了。
【解决方案2】:

您有一个额外的用户选择。试试

var xApprovers = from d in doc.Root
                              .Descendants("document_version")
                 where d.Element("docVersionID").Value == vId
                 select d.Elements("stages")
                              .Elements("stage")
                              .Elements("approver_list")
                              .Elements("approver")
                              .Elements("user");

【讨论】:

  • 如果我去掉 where 语句它可以工作,但它没有......任何想法为什么?谢谢
  • 现在它和我的一样 :) 但两者都返回 IEnumerable&lt;IEnumerable&lt;XElement&gt;&gt;,不是吗?
【解决方案3】:

为什么不这样:

from d in doc.Root.Descendants("document_version")
where d.Element("docVersionID").Value == vId
select d.Elements("stages")
        .Elements("stage")
        .Elements("approver_list")
        .Elements("approver")
        .Elements("user");

doc.Root
   .Descendants("document_version")
   .SingleOrDefault(d => d.Element("docVersionID").Value == vId).Elements("stages") // sic!
   .Elements("stage")
   .Elements("approver_list")
   .Elements("approver")
   .Elements("user");

或者运行 XPath:

(IEnumerable)doc.XPathEvaluate(String.Format("Root/document_version/docVersionID[text()='{0}']/../stages/stage/approver_list/approver/user", vId));

【讨论】:

  • 您的 linq 返回 IEnumerable> 而不是像原始的 IEnumerable 会略有不同
  • @Merick: SingleOrDefault() 应该解决这个问题
  • @Merick:顺便说一句,OP 的查询返回 IEnumerable&lt;XElement&gt; :)
  • SingleOrDefault 将 xml 限制为一个可能不正确的 document_version
  • @Merick:我认为这是文档中的唯一 ID。 OP 可以证明我错了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多