【问题标题】:Get a common element value from a complex XML从复杂的 XML 中获取公共元素值
【发布时间】:2014-01-29 18:44:01
【问题描述】:

我正在处理一个具有非常嵌套结构的 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'] 级别,我很适合获得&lt;ID&gt;,但在/Root/Stuff/Item[@Class='Construct'] 有一个嵌套,需要对每个子进行排序才能获得@ 的&lt;ID&gt; 987654330@

我正在尝试生成整个文档中所有 &lt;ID&gt; 节点的列表,如果可能,键值集合 其中&lt;ID&gt; 是值和元素(其中&lt;ID&gt; 属于) 作为 Key。

我也知道&lt;ID&gt; 在文档中是唯一的,无论其父级如何。所以我可以通过搜索 ID 直接找到任何元素。

我希望这更有意义。

谢谢。

【问题讨论】:

  • 所有 ID 元素值的列表?好的,这听起来相当简单 - 但如果您尝试自己找到答案,您会学到更多。您已经尝试过什么,出了什么问题?
  • 无法创建路径。给定的示例非常简单。实际数据超过 25 MB 的 XML 和敏感数据,所以我不粘贴。
  • “制作路径”是什么意思?您至少能够在 LINQ to XML 中加载文档吗?我没有要求实际数据...
  • 更新了问题。现在是凌晨 2 点 36 分。我有点儿慢。对不起。
  • 目前还不清楚您为什么要使用 XPath,老实说 - 我只是使用元素、后代等。也不清楚您在代码中给出的 XPath 表达式必须是什么使用您提供的 XML。

标签: c# xml


【解决方案1】:

所以你需要获取所有的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)) 
 {
    ...
 }

【讨论】:

  • 如果我将 XML 加载为:var xmlDocument = new XmlDocument();xmlDocument.Load(savefile);,即不使用XDocument
  • 您可以做到,但LINQ to XML 更好且易于使用
【解决方案2】:

您可以使用 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));

【讨论】:

    猜你喜欢
    • 2023-01-26
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多