我必须处理来自我无法控制的第三方REST API的XML响应。问题是XML响应的格式不正确,如下所示:
<XML>
<Meta>
<Status>Success</Status>
<Debug/>
</Meta>
<Result>
<abc>
<DivisionID>tttttttttt</DivisionID>
<UserName><![CDATA[ xxx#xxxxx]]></UserName>
<UserFirstName>xxxx</UserFirstName>
<UserLastName>xxxx</UserLastName>
<UserAccountType>xxxxxxx</UserAccountType>
<UserEmail>xxxxx@xxxxx.xom</UserEmail>
<UserAccountStatus>Active</UserAccountStatus>
</abc>
<def>
<DivisionID/>
<UserName><![CDATA[ xxx#xxxx]]></UserName>
<UserFirstName>yyyy</UserFirstName>
<UserLastName>vvvvvv</UserLastName>
<UserAccountType>uuuuuuuuu</UserAccountType>
<UserEmail>oooo@vvvvvv</UserEmail>
<UserAccountStatus>Active</UserAccountStatus>
</def>
....contd
</Result>
var requestUri = new Uri(uriString);
HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(requestUri);
var httpresponse = (HttpWebResponse)httprequest.GetResponse();
Person people = new Person();
List<Person> lstPerson = (from _person in xmlDoc.Document.Element("Result").Elements("Result")
select new Person
{
userName = Xdocument.Load(httpresponse.GetResponseStream()).Root.ToString(),
userEmail = _person.Element("UserEmail").Value
}).ToList();
我需要检索具有值&#34; abc&#34;的节点。和&#34; def&#34;并将它们存储在UserName中,UserName本身就是根节点,并且还要检索它们之间的值。所以如何做到这一点我尝试了各种各样的方法,但却无法这样做。
答案 0 :(得分:0)
<强>更新强>
要使用Person
的元素名称和userName
的{{1}}子元素的值创建UserEmail
类的列表,您可以执行以下操作:
userEmail
try
{
// Load the XML from the external site
XDocument xmlDoc;
var requestUri = new Uri(uriString);
HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(requestUri);
using (var httpresponse = (HttpWebResponse)httprequest.GetResponse())
using (var stream = httpresponse.GetResponseStream())
using (var reader = new StreamReader(stream))
{
xmlDoc = XDocument.Load(reader);
}
// Extract the name & email.
var people = xmlDoc
// Get the "Result" node
.Root.Elements(xmlDoc.Root.Name.Namespace + "Result")
// Loop through its elements
.SelectMany(result => result.Elements())
// Deserialize the element name and UserEmail sub-element value as a Person
.Select(element => new Person { userName = element.Name.LocalName, userEmail = element.Element(xmlDoc.Root.Name.Namespace + "UserEmail").ValueSafe() })
.ToList();
// Process or return the list of people
}
catch (Exception ex)
{
// Handle any web exception encountered.
Debug.WriteLine(ex);
// Or rethrow if it can't be handled here
throw;
}
原始答案
你的问题不清楚。但如果你问的话
如果我从某些XML加载了
public static class XObjectExtensions { public static string ValueSafe(this XElement element) { return element == null ? null : element.Value; } }
,当列表的每个元素都有自定义元素名称时,有没有办法使用XDocument
反序列化嵌入列表的部分?
然后你可以这样做:
XmlSerializer
XElement.CreateReader()
为该元素创建XDocument
,然后将其传递给XmlReader
进行反序列化。即:
XmlSerializer
给定XML字符串
// Load the document
var doc = XDocument.Parse(xml);
var people = doc
// Navigate to the list
.Root.Elements("Result")
.SelectMany(r => r.Elements())
// Deserialize each element in the list as a KeyValuePair<string, Person>
.Select(element =>
{
var name = element.Name;
element.Name = typeof(Person).DefaultXmlElementName(); // Overwrite name with name used by serializer.
using (var reader = element.CreateReader())
{
var person = (Person)new XmlSerializer(typeof(Person)).Deserialize(reader);
return new KeyValuePair<string, Person>(name.LocalName, person);
}
})
.ToList();
使用扩展方法:
string xml = @"<XML>
<Meta>
<Status>Success</Status>
<Debug/>
</Meta>
<Result>
<abc>
<DivisionID>tttttttttt</DivisionID>
<UserName><![CDATA[ xxx#xxxxx]]></UserName>
<UserFirstName>xxxx</UserFirstName>
<UserLastName>xxxx</UserLastName>
<UserAccountType>xxxxxxx</UserAccountType>
<UserEmail>xxxxx@xxxxx.xom</UserEmail>
<UserAccountStatus>Active</UserAccountStatus>
</abc>
<def>
<DivisionID/>
<UserName><![CDATA[ xxx#xxxx]]></UserName>
<UserFirstName>yyyy</UserFirstName>
<UserLastName>vvvvvv</UserLastName>
<UserAccountType>uuuuuuuuu</UserAccountType>
<UserEmail>oooo@vvvvvv</UserEmail>
<UserAccountStatus>Active</UserAccountStatus>
</def>
</Result>
</XML>
";