使用C#获取XML子节点

时间:2013-04-24 16:33:02

标签: c# xml xmldocument

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

鉴于此XML结构,我将如何使用d:AccountId获取d:NameC#节点的值?

<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>

这是我的第一次尝试。该程序在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;
            }

        }

2 个答案:

答案 0 :(得分:3)

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

目前你的foreach循环正在<id></id>节点上尝试所有这些操作,导致异常,因为没有“title”属性。

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

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
    }
}

或者,如果您只是特别需要这两个值,那么只需使用SelectSingleNode和该节点的完整路径即可。从你的问题来看,听起来没有理由使用迭代。所以你可以这样做;

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

获取帐户名称。

答案 1 :(得分:2)

使用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;
            }
        }