使用 C# 获取 XML 子节点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16197434/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 00:20:41  来源:igfitidea点击:

Obtain XML child nodes using C#

c#xmlxmldocument

提问by NealR

This is my first time attempting to parse XML using C# and feel like I'm running in circles right now. I am calling a WCF web service which, based upon user input, conducts a search through a database against company names. It returns the results in an XML document with each entry formatted as it is below.

这是我第一次尝试使用 C# 解析 XML,感觉就像我现在在兜圈子一样。我正在调用 WCF Web 服务,该服务根据用户输入通过数据库针对公司名称进行搜索。它在 XML 文档中返回结果,每个条目的格式如下。

Given this XML structure, how would I go about obtaining the values for the d:AccountIdand d:Namenodes using C#?

鉴于此 XML 结构,我将如何使用 获取d:AccountIdd:Name节点的值 C#

<entry>
    <id></id>
    <title type=\"text\"></title>
    <updated></updated>
    <author><name /></author>
    <link rel=\"edit\" title=\"Account\" href=\"AccountSet\" />
    <category term=\"Microsoft.Crm.Sdk.Data.Services.Account\" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\" />
    <content type=\"application/xml\">
    <m:properties>
        <d:neu_UniqueId></d:neu_UniqueId>
        <d:AccountId m:type=\"Edm.Guid\"></d:AccountId>
        <d:Name></d:Name>
    </m:properties></content>
</entry>

Here is my first attempt. The program threw an exception at the node3variable.

这是我的第一次尝试。程序在node3变量上抛出异常。

        try
        {
            WebRequest myWebRequest = WebRequest.Create(URL);
            myWebRequest.PreAuthenticate = true;
            myWebRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;

            //myWebRequest.Headers.Add("Access-Control-Allow-Origin", url);

            WebResponse myWebResponse = myWebRequest.GetResponse();
            Stream myFileStreamResult = myWebResponse.GetResponseStream();
            Encoding encoder = System.Text.Encoding.GetEncoding("utf-8");
            StreamReader readStream = new StreamReader(myFileStreamResult, encoder);

            results = readStream.ReadToEnd();

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(results);
            XmlNodeList parentNode = xmlDoc.GetElementsByTagName("entry");

            foreach (XmlNode childNode in parentNode)
            {

                string node = childNode.ToString();
                string node2 = childNode.Value;
                string node3 = childNode.Attributes["title"].Value;
                string node7 = childNode.Attributes["m:properties"].Value;
                string node8 = childNode.Attributes["m:properties\d:AccountId"].Value;
                string node9 = childNode.Attributes["m:properties\d:Name"].Value;
                string node10 = childNode.Attributes["m:properties\d:AccountId"].Value;
            }

        }

采纳答案by evanmcdonnal

Assuming the API reliably returns that XML structure you can simply specify the path to the node as "/entry/m:properties"then call get children. After that you'll want to loop over those nodes, checking for the nodes you want.

假设 API 可靠地返回 XML 结构,您可以简单地指定节点的路径,"/entry/m:properties"然后调用 get children。之后,您将需要遍历这些节点,检查您想要的节点。

Currently your foreach loop is attempting all of those operations on the <id></id>node which causes an Exception because there is no "title" attribute.

当前,您的 foreach 循环正在尝试在<id></id>节点上执行所有这些操作,这会导致异常,因为没有“标题”属性。

So to give some sample code, you're looking for something like this;

所以为了给出一些示例代码,你正在寻找这样的东西;

XmlNode props = root.SelectSingleNode("/entry/m:properties");
for (int i = 0; i < props.ChildNodes.Count; i++)
{
    if (propes.ChildNodes[i].Name = "node I want")
    {
         //do something
    }
}

Or if you specifically only want those two values, then just use SelectSingleNodewith the full path to that node. From your question it sounds like there is no reason to use iteration. So you could simply do;

或者,如果您特别想要这两个值,则只需使用SelectSingleNode该节点的完整路径。从您的问题来看,似乎没有理由使用迭代。所以你可以简单地做;

   string accountName = root.SelectSingleNode("/entry/m:properties/d:Name").InnerXml;

to get the account name.

获取帐户名称。

回答by Primary Key

using Linq2Xml will probably be a little easier.

使用 Linq2Xml 可能会更容易一些。

var xml = "<entry xmlns:m=\"ns1\" xmlns:n=\"ns2\" xmlns:d=\"ns3\">" +
 "<id></id>" +
 "<title type=\"text\"></title>" +
 "<updated></updated>" +
 "<author><name /></author>" +
 "<link rel=\"edit\" title=\"Account\" href=\"AccountSet\" />" +
 "<category term=\"Microsoft.Crm.Sdk.Data.Services.Account\" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\" />" +
 "<content type=\"application/xml\">" +
 "<m:properties>" +
     "<d:neu_UniqueId></d:neu_UniqueId>" +
     "<d:AccountId m:type=\"Edm.Guid\">Account ID</d:AccountId>" +
     "<d:Name>Account Name</d:Name>" +
 "</m:properties></content>" +
"</entry>";

        const string namespaceM = "ns1";
        const string namespaceD = "ns3";

        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
        {
            using (var reader = XmlReader.Create(stream))
            {
                var document = XDocument.Load(reader, LoadOptions.None);
                var contentNode = document.Elements().First().Elements().First(e => e.Name.LocalName == "content");
                var propertiesNode = contentNode.Elements().First(d => d.Name.LocalName == "properties" && d.Name.Namespace == namespaceM);
                var accountIdNode = propertiesNode.Elements().First(d => d.Name.LocalName == "AccountId" && d.Name.Namespace == namespaceD);
                var nameNode = propertiesNode.Elements().First(d => d.Name.LocalName == "Name" && d.Name.Namespace == namespaceD);
                var accountIdText = accountIdNode.Value;
                var nameText = nameNode.Value;
            }
        }