Click here to Skip to main content
15,861,168 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have the following XML Document:

<?xml version="1.0" encoding="utf-8"?>
<csApplication>
<csCollDocuments collection="textValue1" type="dynamic">
<csDocument name="textValue1" master="masterValue" res_loc="location">
<variable name="variableName1" type="string">VariableValue1</variable>
<variable name="variableName2" type="string">VariableValue2</variable>
<variable name="variableName3" type="string">VariableValue3</variable>
</csDocument>
</csCollDocuments>
</csApplication>

I've created the below class to deserialize to, but I'm only getting the first Variable element. How would I go about getting all of them?

[XmlRoot("csApplication")]
public class JobTicketDetails
{
    [XmlElement("csCollDocuments")]
    public Documents Documents { get; set; }
}

public class Documents
{
    [XmlAttribute("collection")]
    public string Collection { get; set; }

    [XmlAttribute("type")]
    public string Type { get; set; }

    [XmlElement("csDocument")]
    public Document Document { get; set; }
}

public class Document
{
    [XmlAttribute("name")]
    public string Name { get; set; }

    [XmlAttribute("master")]
    public string Master { get; set; }

    [XmlAttribute("res_loc")]
    public string ResLoc { get; set; }

    private List<Variable> _Variables = new List<Variable>();
    [XmlElement("variable")]
    public Variable Variable
    {
        get { return _Variables[0]; }

        set { _Variables.Add(value); }
    }
}

public class Variable
{
    [XmlAttribute("name")]
    public string Name { get; set; }

    [XmlAttribute("type")]
    public string Type { get; set; }

    [XmlText]
    public string Text { get; set; }
}
Posted

Replace this

C#
private List<Variable> _Variables = new List<Variable>();
[XmlElement("variable")]
public Variable Variable
{
    get { return _Variables[0]; }

    set { _Variables.Add(value); }
}


by this

C#
[XmlElement("variable")]
public List<Variable> Variables { get; set; }

public Document()
{
    Variables = new List<Variable>();
}


Reason: if you have a list of XML elements that are not enclosed in a parent XML "list element", you define a C# property of that list element and decorate that property by the XmlElement attribute.
If you have an enclosing XML list element, you still define the C# list property, but decorate it with the XmlArray and XmlArrayItem attribute on that property.
 
Share this answer
 
v5
Comments
Tim Groven 22-Feb-12 9:07am    
This worked perfectly! Thank you!
Andreas Gieriet 25-Feb-12 4:23am    
You are welcome! If you like the solution you might consider to rate the it ;-)
When I look at your intended names, I feel that your naming is somewhat artificial. For example, why would you prefer the element csCollDocuments to just Documents. First idea which comes to mind is: you are trying to introduce a notion unique to the application, possibly to avoid naming conflict with some other Documents, as all the words are widely used. That looks like a call for much more comprehensive expression tool, such as XML namespaces. Please see:
http://en.wikipedia.org/wiki/XML_namespace[^],
http://www.w3.org/TR/2006/REC-xml-names11-20060816/[^].

Everything in your code, the style you define your data model (which I like), the structure — tells me that you probably need different, much more consistent approach called Data Contract.

Please see:
http://msdn.microsoft.com/en-us/library/ms733127.aspx[^],
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx[^],
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.aspx[^].

This approach is most flexible and at the same time easiest for development and most non-intrusive.
Please see my past answers where I advocate this approach:
How can I utilize XML File streamwriter and reader in my form application?[^],
Creating property files...[^],
deseralize a json string array[^].

There are many important features in this approach, but in particular, you can use different attribute to modify naming, both name itself via the Name of the [DataMember] attribute and Namespace of the [DataContract] attribute. Please see:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.aspx[^],
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx[^].

[EDIT]

In response to the follow-up discussion and just in case:

Even though the Data Contract could totally solve your problem, you might face the situation where the persistent data format might need some deep customization, due the some peculiarities of the external system. In such difficult cases, the solution is always possible using most flexible XML parsing and generation classes System.Xml.XmlTextWriter and System.Xml.XmlTextReader; this is the fastest way of reading, especially is you need to skip some data.

Please see:
http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.aspx[^], http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.aspx[^].

—SA
 
Share this answer
 
Comments
Tim Groven 22-Feb-12 8:22am    
The sad thing is, those are the real element names, and I can't change them as they come from another system. :( It hurts, I know. :)

Thank you for the links, and I am reading them! :)
Sergey Alexandrovich Kryukov 22-Feb-12 12:03pm    
I understand. There is no such thing as miracle. If you have data structures an external system, you either migrate into incorporating it into your system based on your code, or create an abstraction layer between your system and external one. Some rewriting, in all cases.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900