Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
140 views
in Technique[技术] by (71.8m points)

c# - process XML response and convert to collection which is not in proper format

I have to process XML response from a 3rd party REST API over which I do not have control. problem is the XML response in not in proper format something like this:

<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>
....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();

I need to retrieve the node with value "abc" and "def" and store them in UserName which itself is root node, and also to retrieve the values in between them. so how to do this I tried various ways but was unable to to so.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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:

  1. Loading the XDocument
  2. Navigate to the list you want to deserialize.
  3. For each element, remember the element name, then overwrite it with the class name.
  4. 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;
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...