C# 使用XPath获取特定节点的所有子元素值

C# 使用XPath获取特定节点的所有子元素值,c#,xml,xpath,C#,Xml,Xpath,我正在使用XPath从XML文档中读取元素。具体地说,我想返回作为指定元素的子元素的任何元素的值(这里指定的元素是,这些元素有一位数的值。因此我想返回1的所有子元素 以下是XML: <MissionObjectives> <Theme themeName="Gothic"> <SceneryType> 1 <Objective> Do a river thing. </Objec

我正在使用XPath从XML文档中读取元素。具体地说,我想返回作为指定元素的子元素的任何元素的值(这里指定的元素是
,这些元素有一位数的值。因此我想返回
1
的所有子元素

以下是XML:

<MissionObjectives>
<Theme themeName="Gothic">
    <SceneryType>
    1
        <Objective>
        Do a river thing.
        </Objective>
        <Objective>
        Get all men to the other side of the river.
        </Objective>
    </SceneryType>
    <SceneryType>
    2
        <Objective>
        Climb some trees!
        </Objective>
        <Objective>
        Shoot the tree!
        </Objective>
    </SceneryType>
</Theme>
我曾尝试通过堆栈溢出查找类似问题,但似乎找不到任何适用于XPath的内容。我无法使用LINQ to XML来解决此问题。知道如何返回各种“目标”节点的所有值吗


为您的帮助干杯!

首先,您的xml数据在搜索元素的文本节点中有回车符、换行符和空格。请记住,xml节点可以是元素、属性或文本(以及其他节点类型)。下面的解决方案有点“老手”的一面,可能有点“老手”,但它应该可以工作。我不确定您想要的是子元素文本数据还是整个子元素,但我只返回子文本节点数据(没有回车符和换行符)。此外,虽然此解决方案严格意义上不使用LINQ to XML,但它使用一个LINQ表达式

    private List<string> getSceneryTypeObjectiveTextList(string xml, int sceneryTypeId, string xpath = "/MissionObjectives/Theme/SceneryType")
    {
        List<string> result = null;
        XmlDocument doc = null;
        XmlNodeList sceneryTypeNodes = null;

        try
        {
            doc = new XmlDocument();
            doc.LoadXml(xml);

            sceneryTypeNodes = doc.SelectNodes(xpath);

            if (sceneryTypeNodes != null)
            {
                if (sceneryTypeNodes.Count > 0)
                {
                    foreach (XmlNode sceneryTypeNode in sceneryTypeNodes)
                    {
                        if (sceneryTypeNode.HasChildNodes)
                        {
                            var textNode = from XmlNode n in sceneryTypeNode.ChildNodes
                                           where (n.NodeType == XmlNodeType.Text && n.Value.Replace("\r", "").Replace("\n", "").Replace(" ", "") == sceneryTypeId.ToString())
                                           select n;

                            if (textNode.Count() > 0)
                            {
                                XmlNodeList objectiveNodes = sceneryTypeNode.SelectNodes("Objective");

                                if (objectiveNodes != null)
                                {
                                    result = new List<string>(objectiveNodes.Count);

                                    foreach (XmlNode objectiveNode in objectiveNodes)
                                    {
                                        result.Add(objectiveNode.InnerText.Replace("\r", "").Replace("\n", "").Trim());
                                    }

                                    // Could break out of the iteration, here, if we know that SceneryType is always unique (i.e. - no duplicates in Element text node)
                                }
                            }
                        }
                    }
                }
            }

        }
        catch (Exception ex)
        {
            // Handle error
        }
        finally
        {

        }

        return result;
    }


    private sampleCall(string filePath, int sceneryTypeId)
    {
        List<string> compatibleObjectivesList = null;

        try
        {
            compatibleObjectivesList = getSceneryTypeObjectiveTextList(File.ReadAllText(filePath), sceneryTypeId);
        }
        catch (Exception ex)
        {
    // Handle error
        }
        finally
        {

        }
    }
private List getSceneryTypeObjectiveTextList(字符串xml,int sceneryTypeId,字符串xpath=“/MissionObjectives/Theme/SceneryType”)
{
列表结果=空;
XmlDocument doc=null;
XmlNodeList sceneryTypeNodes=null;
尝试
{
doc=新的XmlDocument();
doc.LoadXml(xml);
sceneryTypeNodes=doc.SelectNodes(xpath);
if(sceneryTypeNodes!=null)
{
如果(sceneryTypeNodes.Count>0)
{
foreach(sceneryTypeNodes中的XmlNode sceneryTypeNode)
{
if(sceneryTypeNode.HasChildNodes)
{
var textNode=来自sceneryTypeNode.ChildNodes中的XmlNode n
其中(n.NodeType==XmlNodeType.Text&&n.Value.Replace(“\r”,”).Replace(“\n”,”).Replace(“,”).Replace(“,”)==sceneryTypeId.ToString())
选择n;
如果(textNode.Count()>0)
{
XmlNodeList objectiveNodes=sceneryTypeNode.SelectNodes(“目标”);
if(objectiveNodes!=null)
{
结果=新列表(objectiveNodes.Count);
foreach(objectiveNodes中的XmlNode objectiveNode)
{
result.Add(objectiveNode.InnerText.Replace(“\r”和“).Replace(“\n”和“).Trim());
}
//如果我们知道SceneryType始终是唯一的(即-元素文本节点中没有重复项),则可能在这里中断迭代
}
}
}
}
}
}
}
捕获(例外情况除外)
{
//处理错误
}
最后
{
}
返回结果;
}
私有sampleCall(字符串文件路径,int sceneryTypeId)
{
List compatibleObjectivesList=null;
尝试
{
compatibleObjectivesList=getSceneryTypeObjectiveTextList(File.ReadAllText(filePath),sceneryTypeId);
}
捕获(例外情况除外)
{
//处理错误
}
最后
{
}
}

使用XDocument要简单得多:

var doc = XDocument.Load(objectivesPath + "MissionObjectives" + chosenTheme + ".xml");
要获取所有第一个SceneryType子节点,请执行以下操作:

var node = doc.XPathSelectElement("//MissionObjectives/Theme/SceneryType[1]"); 
要获取第二个目标节点,请执行以下操作:

var node = doc.XPathSelectElement("//MissionObjectives/Theme/SceneryType/Objective[2]");
更多样品

太好了,这(加上一些厚脸皮的环)正是我需要的!谢谢。
var node = doc.XPathSelectElement("//MissionObjectives/Theme/SceneryType/Objective[2]");