从复杂的XML中获取公共元素值

时间:2014-01-28 22:27:47

标签: c# xml

我正在处理一个具有非常嵌套结构的XML文件:

<?xml version="1.0" encoding="utf-8"?>
<Root>
    <Stuff>
        <Item Class="Consumable">
            <CalledAs>ResourceAlpha</CalledAs>
            <ID>ResourceAlpha25367</ID>
        </Item>
        <Item Class="Consumable">
            <CalledAs>ResourceAlpha</CalledAs>
            <ID>ResourceAlpha25368</ID>
        </Item>
        <Item Class="Consumable">
            <CalledAs>ResourceAlpha</CalledAs>
            <ID>ResourceAlpha25371</ID>
        </Item>
        <Item Class="Consumable">
            <CalledAs>ResourceAlpha</CalledAs>
            <ID>ResourceAlpha25372</ID>
        </Item>
        <Item Class="Consumable">
            <CalledAs>ResourceBeta</CalledAs>
            <ID>ResourceBeta25376</ID>
        </Item>
        <Item Class="Consumable">
            <CalledAs>ResourceBeta</CalledAs>
            <ID>ResourceBeta25377</ID>
        </Item>
        <Item Class="Consumable">
            <CalledAs>ResourceBeta</CalledAs>
            <ID>ResourceBeta25381</ID>
        </Item>
        <Item Class="Consumable">
            <CalledAs>ResourceBeta</CalledAs>
            <ID>ResourceBeta25384</ID>
        </Item>
        <Item Class="Consumable">
            <CalledAs>ResourceBeta</CalledAs>
            <ID>ResourceBeta25388</ID>
        </Item>

        <Item Class="Construct">
            <Named>ClosedFolders</Named>
            <ID>ClosedFolders25393</ID>
            <StorageCabinet>(102, 0, 94)</StorageCabinet>
            <AssignedTo>Colonist</AssignedTo>
            <Assigned Class="Consumable">
                <CalledAs>ResourceBeta</CalledAs>
                <ID>ResourceBeta25238</ID>
            </Assigned>
        </Item>
        <Item Class="Construct">
            <Named>ClosedFolders</Named>
            <ID>ClosedFolders25394</ID>
            <StorageCabinet>(105, 0, 95)</StorageCabinet>
            <AssignedTo>Colonist</AssignedTo>
        </Item>
        <Item Class="Construct">
            <Named>ClosedFolders</Named>
            <ID>ClosedFolders25395</ID>
            <StorageCabinet>(103, 0, 92)</StorageCabinet>
            <AssignedTo>Colonist</AssignedTo>
            <Assigned Class="Consumable">
                <CalledAs>ResourceAlpha</CalledAs>
                <ID>ResourceBeta45232</ID>
            </Assigned>         
        </Item>

    </Stuff>
</Root>

现在,我需要获取所有ID的列表,这样当我添加新的ConsumableAssigned时,我就可以生成(并确保它是唯一的)新ID

以下是我加载文件的方式:

    String savefile = Settings.Default.SelectedSaveFilePath;

    var xmlDocument = new XmlDocument();
    xmlDocument.Load(savefile);

    var selectSingleNode = xmlDocument.SelectSingleNode("/Root/Stuff/Item[@Class='Consumable']");
    if (selectSingleNode != null)
    {
      // Attempt to loop
    }

现在,在/Root/Stuff/Item[@Class='Consumable']的级别,我很适合获取<ID>但是/Root/Stuff/Item[@Class='Construct']处有一个嵌套,需要按照每个子版本来获取<ID>

<Assigned Class="Consumable">

我正在尝试生成整个文档中所有<ID>个节点的列表,如果可能的话,还会生成一个键值集合,其中<ID>是值,元素(<ID>所属的元素)为Key。

我也知道<ID>在文档中是唯一的,无论其父级是什么。所以我可以通过只搜索ID直接找到任何元素。

我希望这更有意义。

感谢。

2 个答案:

答案 0 :(得分:2)

因此,您需要获取所有ID,并且当您想要添加新项目时,您需要检查是否存在具有给定ID的项目?

var idList = XDocument.Load("path")
                      .Descendants("ID")
                      .Select(x => (string)x);

if(idList.Contains(givenId))
{ 
    ...
}

或使用HashSet进行更快速的搜索:

 var hashSet = new HashSet<string>(idList);
 if(hashSet.Contains(givenId)) 
 {
    ...
 }

答案 1 :(得分:1)

您可以使用HashSet进行快速查找

var ids = new HashSet<string>( 
                XDocument.Load(filename)
                    .Descendants("ID")
                    .Select(x => (string)x));

或(在编辑中使用XmlDocument类)。

XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(filename);
var ids = new HashSet<string>(
                xmlDocument.GetElementsByTagName("ID")
                    .Cast<XmlNode>()
                    .Select(x => x.InnerText));