在C#中读取特定的XML数据

时间:2015-02-13 09:47:33

标签: c# xml

现在,我想在XML文件中获取一些特定信息。以下是我对XML的看法:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <world>
    <region name="TestRegion">
      <area name="TestArea">
        <building name="Outside">
          <room name="TutorialRoom">
            <stuffToTake>All the text I want to take</stuffToTake>
          </room>
        </building>
      </area>
    </region>
  </world>
</root>

我在线查看了如何使用代码执行此操作,并且我看到了此实现。我刚刚将它改编为我的代码:

XElement xelement = XElement.Load("..\\..\\LocationDatabase.xml");

var TextToDisplay = from regions in xelement.Elements("world")
                   where (string)regions.Element("region").Attribute("name") == "TestRegion"
                   where (string)regions.Element("region").Element("area").Attribute("name") == "TestArea"
                   where (string)regions.Element("region").Element("area").Element("building").Attribute("name") == "Outside"
                   where (string)regions.Element("region").Element("area").Element("building").Element("room").Attribute("name") == "TutorialRoom"
                   select regions;

foreach (var xEle in TextToDisplay)
{
    Console.WriteLine(xEle.Element("region").Element("area").Element("building").Element("room").Element("stuffToTake").Value);
}

到目前为止,这很好用。 Working Console window 这里的问题是我在XML上面添加了一些数据

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <world>
   <region name="LolNope">
      <area name="TestArea">
        <building name="Outside">
          <room name="TutorialRoom">
            <stuffToTake>All the text I want to take</stuffToTake>
          </room>
        </building>
      </area>
    </region>
    <region name="TestRegion">
      <area name="TestArea">
        <building name="Outside">
          <room name="TutorialRoom">
            <stuffToTake>All the text I want to take</stuffToTake>
          </room>
        </building>
      </area>
    </region>
  </world>
</root>

然后,它只是变成一个空的控制台窗口: Blank, empty Console Window

这究竟是什么问题?我假设它检查第一个区域是否有名称TestRegion,但是因为它没有失败并且停止检查其余区域。

2 个答案:

答案 0 :(得分:1)

您需要做的是将您的查询链接到linq-to-xml,一次选择每组元素。

// all worlds
var worlds = xelement.Elements("world");

// all regions in the worlds where the attribute "name" is "TestRegion"
var regions = worlds.Elements("region")
                    .Where (region => (string)region.Attribute("name") == "TestRegion");

// all areas in the specified regions where the attribute "name" is "TestArea"
var areas = regions.Elements("area")
                   .Where (area => (string)area.Attribute("name") == "TestArea");

// all buildings in the specified areas where the attribute "name" is "Outside"
var buildings = areas.Elements("building")
                     .Where (building => (string)building.Attribute("name") == "Outside");

// all rooms in the specified buildings where the attribute "name" is "TutorialRoom"
var rooms = buildings.Elements("room")
                     .Where (room => (string)room.Attribute("name") == "TutorialRoom");

// all stuff to take in the specified rooms
var stuffs = rooms.Elements("stuffToTake");

// all the contents of the stuffs as an enumerable (there might be more than one, after all)
var values = stuffs.Select (stuff => stuff.Value);

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

而且,没有中间变量:

var values = xelement.Elements("world")
    .Elements("region").Where (region => (string)region.Attribute("name") == "TestRegion")
    .Elements("area").Where (area => (string)area.Attribute("name") == "TestArea")
    .Elements("building").Where (building => (string)building.Attribute("name") == "Outside")
    .Elements("room").Where (room => (string)room.Attribute("name") == "TutorialRoom")
    .Elements("stuffToTake")
    .Select(stuff => stuff.Value);

答案 1 :(得分:1)

你可以这样做,如果你想深入了解东西ToTake:

var result = root.Elements("world")
                 .Elements("region")
                 .Where (r => r.Attribute("name").Value == "TestRegion")
                 .Elements("area")
                 .Elements("building")
                 .Elements("room")
                 .Elements("stuffToTake")
                 .Select (r => r.Value);

result.Dump();

如果要在更深层次上过滤区域或建筑物或房间,只需在选择元素后应用where子句,然后按属性过滤:

                  .Elements("region")
                 .Where (r => r.Attribute("name").Value == "TestRegion")
                 .Elements("area")
                 .Where(ar => ar.Attribute("name").Value == "TestArea")
                 .Elements("building")
                 .Where(bui => bui.Attribute("name").Value == "Outside")
                 .Elements("room")

我倾向于将所有方法都放在前面的方法之下,但如果这更适合您的阅读和理解,您也可以将Where()方法直接置于Element -selection之后:

.Elements("region").Where (r => r.Attribute("name").Value == "TestRegion")
.Elements("area").Where(ar => ar.Attribute("name").Value == "TestArea")
.Elements("building").Where(bui => bui.Attribute("name").Value == "Outside")
.Elements("room")...

重要的部分是按属性名称进行过滤。亲自尝试一下: http://share.linqpad.net/vns5le.linq