Update
To create a list of your Person
classes using element names for userName
and the value of the UserEmail
sub-element for userEmail
, you can do the following:
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;
}
Using the extension method
public static class XObjectExtensions
{
public static string ValueSafe(this XElement element)
{
return element == null ? null : element.Value;
}
}
Original Answer
Your question is unclear. But if you are asking
If I have loaded an XDocument
from some XML, is there a way using XmlSerializer
to deserialize a portion which is an embedded list when each element of the list has a custom element name?
Then you can do this as follows:
- Loading the
XDocument
- Navigate to the list you want to deserialize.
- For each element, remember the element name, then overwrite it with the class name.
- Use
XElement.CreateReader()
to create an XmlReader
for just that element, then pass it to an XmlSerializer
for deserialization.
I.e.:
// 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();
Given the XML string
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>[email protected]</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>
";
Using the extension method:
public static class XmlSerializationHelper
{
public static string DefaultXmlElementName(this Type type)
{
var xmlType = type.GetCustomAttribute<XmlTypeAttribute>();
if (xmlType != null && !string.IsNullOrEmpty(xmlType.TypeName))
return xmlType.TypeName;
var xmlRoot = type.GetCustomAttribute<XmlRootAttribute>();
if (xmlRoot != null && !string.IsNullOrEmpty(xmlRoot.ElementName))
return xmlRoot.ElementName;
return type.Name;
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…