【问题标题】:Reading Complex XML Attributes读取复杂的 XML 属性
【发布时间】:2012-12-08 23:52:43
【问题描述】:

我有一个 XML 文件,它使用了包含数据的属性和标签的组合。

我无法控制 XML 文件的结构,但我目前正在切换设备以查看 LINQ 来解析它,并想知道是否有关于如何最好地处理这种结构的意见:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE call_flow SYSTEM "../../../../dtds/Callflow_1-1.dtd">
<call_flow version="1.1" serial="13903" first_element="Element1">
  <element_def name="Element1">
    <voice class="com.classname.Name">
      <static>Element1.xml</static>
    </voice>
    <exit_state name="done">
      <next_element>Element2</next_element>
    </exit_state>
  </element_def>
  <element_def name="Element2">
    <voice class="com.classname.Name2">
      <static>Element2.xml</static>
    </voice>
    <exit_state name="option1">
      <next_element>Element3</next_element>
    </exit_state>
    <exit_state name="option2">
      <next_element>Element4</next_element>
    </exit_state>
  </element_def>
  <element_def name="Element3">
    <voice class="com.classname.Name3">
      <static>Element3.xml</static>
    </voice>
    <exit_state name="done">
      <next_element>Element4</next_element>
    </exit_state>
  </element_def>
  <element_def name="Element4">
    <decision>
      <class src="com.classname.Name4"/>
    </decision>
    <exit_state name="0">
      <next_element>Element3</next_element>
    </exit_state>
    <exit_state name="1">
      <next_element>Element5</next_element>
    </exit_state>
  </element_def>
  <element_def name="Element5">
    <voice class="com.classname.Name5">
      <static>element5.xml</static>
    </voice>
  </element_def>
</call_flow>

我可以找到大量 LINQ 代码示例,但我并没有真正了解如何获取 Next_Element 和 element_def“名称”属性的值。

如果有人可以提供帮助并可能为我指明正确的方向,我将不胜感激。

【问题讨论】:

  • 对于元素 Element4 有两个 next_element 节点。你想要两者都在结果中?

标签: c# xml linq visual-studio-2008


【解决方案1】:
XDocument xdoc = XDocument.Load(path_to_xml);
var query = from ed in xdoc.Descendants("element_def")
            select new
            {
               Name = (string)ed.Attribute("name"),
               NextElements = ed.Elements("exit_state")
                                .Select(es => (string)es.Element("next_element"))
            };

此查询将返回匿名对象序列,其中将具有包含element_def 名称的Name 属性,并且下一个元素的名称为IEnumerable&lt;string&gt;

【讨论】:

  • 快速跟进 - 刚接触 LINQ 我假设有更有效的方法来做这样的事情: foreach (var p in data) { //Output the Element Name Console.WriteLine("{0 }", p.Name); //输出下一个元素 //计算没有下一个元素的返回元素 if (p.Name.Contains("Return")) { //什么都不做,因为它没有下一个元素 } else{ foreach (string prp in p.NextElements ) { Console.WriteLine("\t\t{0}",prp.ToString()); } } }
【解决方案2】:

这个呢:

var doc =  XDocument.Load("myXml.xml");
var list = doc.Descendants("element_def")
              .Select(x => new
              {
                 elDefName = x.Attribute("name").Value,
                 nextEl = x.Descendants("next_element").Select(y=> y.Value).ToList()
              });

它将返回匿名对象的IEnumerable,其中elDefName 将是element_def 节点的名称属性的值,nextEl 将包含可能的next_element 价值观。

【讨论】:

  • 太棒了 - 我会试试这些,看看我的位置 - 真的很欣赏我第一眼看到的东西的简单性。
  • 刚接触 LINQ - 有没有比嵌套 foreach 循环更好的方法来遍历结果?
  • 是的,您可以使用嵌套循环。这取决于您的用例是什么。例如。如果你想创建一些代表 XML 结构的对象,没关系。但是,如果您只想进行一些过滤,最好在上面发布的查询中附加一些 where 条件。
  • 最终目标是删除带有附加数据的 Visio 形状,因此我正在为每个元素构建一个对象并提取子元素属性以作为形状数据插入。似乎我可能采用这种方法走在正确的轨道上。非常感谢指点。
  • 是的,那么您可以使用嵌套循环。 (请...将最多帮助您解决问题的答案标记为已回答 - 不管是我的答案 :-) - 它会帮助社区)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 1970-01-01
相关资源
最近更新 更多