【问题标题】:Linq to XML simple get attribute from node statementLinq to XML 从节点语句中简单获取属性
【发布时间】:2014-10-09 04:45:30
【问题描述】:

这里是sn-p的代码:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml"));
string result = "";
var childType = from t in themes.Descendants()
    where t.Attribute("name").Value.Equals(theme)
    select new { value = t.Attribute("type").Value };

foreach (var t in childType) {
    result += t.value;
}
return result;

这是 XML:

<?xml version="1.0" encoding="utf-8" ?>
<themes>
  <theme name="Agile">
    <root type="Project">
      <node type="Iteration" >
        <node type="Story">
          <node type="Task"/>
        </node>
      </node>
    </root>
  </theme>
  <theme name="Release" >
    <root type="Project">
      <node type="Release">
        <node type="Task" />
        <node type="Defect" />
      </node>
    </root>
  </theme>
</themes>

我做错了什么?我不断收到“对象未设置为对象的实例”异常。

我要返回的是基于父节点类型的所选节点的类型,即如果主题是“敏捷”并且父节点是“项目”,那么返回值应该是“迭代”。这是最终的结果,但我从来没有走到那一步,因为我被你在上面看到的东西困住了。

【问题讨论】:

  • 我编辑了我的答案以符合您添加的信息。

标签: c# linq-to-xml


【解决方案1】:

我想你想要更接近这个的东西:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml"));
string result = "";
var childType = from t in themes.Descendants("theme")
                where t.Attribute("name").Value.Equals(theme)
                select new { value = t.Descendants().Attribute("type").Value };

foreach (var t in childType) {
    result += t.value;
}
return result;

编辑: 根据您的其他信息,也许这更接近:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml"));
string result = "";
var childType = from t in themes.Descendants("theme")
                where t.Attribute("name").Value.Equals(theme)
                where t.Element("node").Attribute("type").Value == parent
                select new { value = t.Descendants().Attribute("type").Value };

foreach (var t in childType) {
    result += t.value;
}
return result;

编辑 2:这对我有用:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml"));
string result = "";
var theme = "Agile";
var parent = "Project";
var childType = from t in themes.Descendants("theme")
            where t.Attribute("name").Value.Equals(theme)
            where t.Element("root").Attribute("type").Value == parent
            from children in t.Element("root").Descendants()
            select new { value = children.Attribute("type").Value };
foreach (var t in childType) {
    result += t.value;
}
return result;

编辑 3:这是完整的工作程序,只需将其放入控制台应用程序的类中即可。

static void Main(string[] args)
        {
            var xml = "<themes><theme name='Agile'><root type='Project'><node type='Iteration' ><node type='Story'><node type='Task'/></node></node></root></theme><theme name='Release' ><root type='Project'><node type='Release'><node type='Task' /><node type='Defect' /></node></root></theme></themes>";
            XDocument themes = XDocument.Parse(xml);
            string result = "";
            var theme = "Agile";
            var parent = "Project";
            var childType = from t in themes.Descendants("theme")
                            where t.Attribute("name").Value.Equals(theme)
                            where t.Element("root").Attribute("type").Value == parent
                            from children in t.Element("root").Descendants()
                            select new { value = children.Attribute("type").Value };

            foreach (var t in childType)
            {
                Console.WriteLine(t.value);
            }

            Console.Read();

        }

【讨论】:

  • FirstNode 没有方法版本,它是一个没有属性方法的属性。
  • 我必须在 select 语句中将 .First() 添加到 t.Descendants() 以使其编译,但是我仍然无法将对象设置为对象异常的实例跨度>
  • 您的第二次编辑正在为我返回空白值。我不能与我的 xml 布局有关吗?
  • 我再次更新了根据您提供的内容显示完整的工作示例。如果它仍然不起作用,请查看您的 xml 并确保它与我的格式相同。除非 xml 中有其他内容,否则它应该对您有用。
【解决方案2】:

好的,这就是我最后所做的,它不是很漂亮,但它确实有效。 它基于 Pramodh 几周后的回答。

string result = "";
                var childType = themes.Descendants("theme")
                                               .Where(x => x.Attribute("name").Value == theme)
                                               .Where(x => x.Descendants("node").First().Attribute("type").Value == parentType)
                                               .Select(x => x.Descendants("node").First().Descendants().First().Attribute("type").Value);

                foreach (var t in childType) {
                    result += t;
                }
                return result;

现在如果我传入主题“敏捷”和父级“迭代”,它会返回故事。

就像我说的不是很漂亮,但它有效。

感谢所有发布答案的人。

【讨论】:

    【解决方案3】:

    您的查询中有两个错误。

    第一个是:

    from t in themes.Descendants()
    

    这将为您提供所有 themes 元素。
    如果你想要 theme 元素,你必须通过过滤来指定它:

    from t in themes.Descendants("theme")
    

    因此第二个错误将是

    select new { value = t.Attribute("type").Value }
    

    因为t 将是一个theme 元素,没有“类型”属性。
    我对此无能为力,因为尚不清楚最终结果必须是什么。

    编辑:根据添加的信息,这应该可以解决问题:

            var childType =
                from t in doc.Descendants("theme")
                where t.Attribute("name").Value.Equals(theme)
                select t.Element("root")
                        .Element("node")
                        .Attribute("type").Value;
    

    但是,这意味着从具有相同 theme 名称的节点中检索多种类型。
    如果类型始终相同,则应考虑调用.SingleOrDefault()。

    【讨论】:

      【解决方案4】:

      我不清楚你的问题。这是我的解决方案(据我了解)

      var childType = themes.Descendants("theme")
                                   .Where(X => X.Attribute("name").Value == "Agile")
                                   .Where(X => X.Descendants("root").Attributes("type").First().Value == "Project")
                                   .Select(X => X.Descendants("node").Attributes("type").First().Value);
      

      【讨论】:

        猜你喜欢
        • 2016-06-10
        • 1970-01-01
        • 2012-09-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-02
        • 1970-01-01
        • 2012-09-01
        相关资源
        最近更新 更多