0

Sorry for the horrible title, I wasn't sure what the proper phrasing is.

I've been using this code to parse some XML:

[Serializable()]
public class Report
{
    [XmlElement("AttachedFiles")]
    public AttachedFiles attachedFiles;

    public Report()
    {
        attachedFiles = null;
    }
}

[Serializable()]
[XmlRoot("nodes")]
public class ReportList
{
    [XmlElement("node", typeof(Report))]
    public Report[] reportList;
}

[Serializable()]
[XmlRoot("AttachedFiles")]
public class AttachedFiles
{
    [XmlElement("AttachedFile")]
    public List<string> attachedFiles;
}

The XML looks something like this:

<nodes>
    <node>
        <AttachedFiles>
            <AttachedFile>File1</AttachedFile>
            <AttachedFile>File2</AttachedFile>
        </AttachedFiles>
    </node>
</nodes>

The problem I'm having is that this ends up with me having to call Report.attachedFiles.attachedFiles to get the List. Is there a way for me to only call Report.attachedFiles and get the List? I know this is a really minor problem, but it's bothering quite a bit.

EDIT

This is what the code looks like after help from @xDaevax.

[Serializable()]
public class Report
{
    [XmlArray(ElementName = "AttachedFiles"), XmlArrayItem(ElementName = "AttachedFile")]
    public List<string> AttachedFiles;

    public Report()
    {
        attachedFiles = null;
    }
}

[Serializable()]
[XmlRoot("nodes")]
public class ReportList
{
    [XmlElement("node", typeof(Report))]
    public Report[] reportList;
}

Thanks for the help!

1 Answer 1

1

Here is what I came up with (though I did not have your JiraReport class handy).

[Serializable()]
public class Report {

    [XmlIgnore()]
    private AttachedFiles _attachedFiles;
    public Report() {
            attachedFiles = null;
    } // end constructor

    [XmlArray(ElementName = "AttachedFiles"), XmlArrayItem(ElementName = "AttachedFile")]
    public AttachedFiles Files {
            get { return _attachedFiles; }
            set { _attachedFiles = value; }
    } // end property Files

} // end class Report

[Serializable()]
[XmlRoot("ReportList")]
public class ReportList {

    [XmlIgnore()]
    private Report[] _reports;

    public ReportList() {
        _reports = null;
    } // end constructor

    [XmlArray(ElementName = "nodes"), XmlArrayItem(ElementName = "node")]
    public Report[] Reports {
            get { return _reports; }
            set { _reports = value; }
    } // end property Reports

} // end class ReportList

[Serializable()]
public class AttachedFiles : List<string> {

} // end class AttachedFiles

Using the XmlArray and ArrayItem on a collection property simplifies the attribute usage and makes the code easier to read. Also, because the AttachedFiles class inherits from a list of string, it removes a level of depth from your object graph so the call isn't redundant anymore. You could also add a function on the ReportList class that loops and returns all attached files for all reports for you (functions will not be serialized by the XmlSerializer).

Edit: Here is some MSDN documentation that explains the feature usage:

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlarrayitemattribute(v=vs.100).aspx Also, see this BlackWasp article that has a nice walkthrough of XML serialization involving arrays. http://www.blackwasp.co.uk/xmlarrays.aspx

Sign up to request clarification or add additional context in comments.

2 Comments

Sorry, it was meant to be using the Report class. I've edited the code above. So much for hiding my actual work...
Thanks! The [XmlArray(ElementName = "AttachedFiles"), XmlArrayItem(ElementName = "AttachedFile")] is what I needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.