1

I'm trying to build a CDA document by serializing my object to XML, here's the XML part that causing me some troubles :

<component>
    <section>
        <templateId root='2.16.840.1.113883.10.20.1.11'/>
        <templateId root='1.3.6.1.4.1.19376.1.5.3.1.3.6'/>
        <!--<id root='' extension=''/>-->
        <code code="11450-4" displayName="PROBLEM LIST" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC"/>
        <title>Active Problem - Problem List</title>
        <text>
            <table>
                <thead>
                    <tr>
                        <th>Problem</th>
                        <th>Code</th>
                        <th>Code System</th>
                        <th>Start Date</th>
                        <th>Status</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>Asthma</td>
                        <td>195967001</td>
                        <td>SNOMED CT</td>
                        <td></td>
                        <td>Active</td>
                    </tr>
                    <tr>
                        <td>Costal chondritis</td>
                        <td>64109004</td>
                        <td>SNOMED CT</td>
                        <td></td>
                        <td>Active</td>
                    </tr>
                    <tr>
                        <td>No impairment</td>
                        <td>66557003</td>
                        <td>SNOMED CT</td>
                        <td></td>
                        <td>Active</td>
                    </tr>
                </tbody>
            </table>
        </text>
    </section>
</component>

And here are my C# classes for serializing it :

public class Section
{
    [XmlElement("templateId")]
    public List<IdElement> TemplateIds { get; set; }
    [XmlElement("code")]
    public CodeElement Code { get; set; }
    [XmlElement("title")]
    public string Title { get; set; }
    [XmlElement("text")]
    public Text Text { get; set; }
}
public class Text
{
    [XmlElement("table")]
    public Table.Table Table { get; set; }

    [XmlArray("list")]
    [XmlArrayItem("item")]
    public List<string> List { get; set; }

    [XmlElement("paragraph")]
    public List<string> Paragraphs { get; set; }
}
public class Table
{
    [XmlElement("thead")]
    public TRow Header { get; set; }
    [XmlElement("tbody")]
    public TRow Body { get; set; }
}
public class TRow
{
    [XmlArray(ElementName = "tr", Namespace = "")]
    [XmlArrayItem("td")]
    public List<string> RowData { get; set; }

    [XmlArray(ElementName = "tr", Namespace = "")]
    [XmlArrayItem("th")]
    public List<string> HeaderData { get; set; }
}

But when I try to serialize my CDA object now, it says that the type tr is already present in the Namespace, so I guess that this kind of XML table already exists, but I can't find a way to do it properly. Is there any solution to get around this problem ?

Here's the error log (without the stack trace) :

System.InvalidOperationException: There was an error reflecting type 'Project.Cda.Core.ClinicalDocument'. ---> System.InvalidOperationException: There was an error reflecting property 'Component'. ---> System.InvalidOperationException: There was an error reflecting type 'Project.Cda.Core.Components.BaseComponent'. ---> System.InvalidOperationException: There was an error reflecting property 'Components'. ---> System.InvalidOperationException: There was an error reflecting type 'Project.Cda.Core.Components.Component'. ---> System.InvalidOperationException: There was an error reflecting property 'Section'. ---> System.InvalidOperationException: There was an error reflecting type 'Project.Cda.Core.Components.Section'. ---> System.InvalidOperationException: There was an error reflecting property 'Text'. ---> System.InvalidOperationException: There was an error reflecting type 'Project.Cda.Core.Components.Text'. ---> System.InvalidOperationException: There was an error reflecting property 'Table'. ---> System.InvalidOperationException: There was an error reflecting type 'Project.Cda.Core.Components.Table.Table'. ---> System.InvalidOperationException: There was an error reflecting property 'Header'. ---> System.InvalidOperationException: There was an error reflecting type 'Project.Cda.Core.Components.Table.TRow'. ---> System.InvalidOperationException: There was an error reflecting property 'HeaderData'. ---> System.InvalidOperationException: The XML element 'tr' from namespace '' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.

Antoine Thiry
  • 2,362
  • 4
  • 28
  • 42
  • 2
    In `TRow` You have `[XmlArray(ElementName = "tr", Namespace = "")]` on both `RowData` and `HeaderData`. That can't work. – dbc Sep 26 '17 at 09:18
  • @dbc Hmm, thank you, I'll try something else. Is my only option to create seperate classes for Header and Body data ? – Antoine Thiry Sep 26 '17 at 09:21
  • 2
    That's by far the easiest. Other options include 1) Use [`[XmlChoiceIdentifierAttribute]`](https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlchoiceidentifierattribute(v=vs.110).aspx) to set up an `enum` array indicating whether a `` child element is a `` or ``. 2) Implement [`IXmlSerializable`](https://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly). (Don't do it!) 3) Do some trick with nested serializations inside an `[XmlAnyElement]` property as shown e.g. [here](https://stackoverflow.com/a/33180709/3744182). – dbc Sep 26 '17 at 09:27
  • Alright thanks, would have been cleaner to do it with the same element name but it works, thanks ! – Antoine Thiry Sep 26 '17 at 09:41

1 Answers1

3

You are getting the error because, in TRow, You have

[XmlArray(ElementName = "tr", Namespace = "")]

on both RowData and HeaderData. That can't work -- you are trying to specify the same element name for two different properties, and so get the error that you see, namely that The XML element 'tr' from namespace '' is already present in the current scope.

Furthermore, there's an additional problem with your models. The <tr> elements inside <tbody> repeat, but your data model only allows for one <tr> element per body.

The following fixes both problems by introducing an intermediate TablePart to represent either the header and body portions of the table:

public class Table
{
    [XmlElement("thead")]
    public TablePart Header { get; set; }

    [XmlElement("tbody")]
    public TablePart Body { get; set; }
}

public class TablePart
{
    [XmlElement(ElementName = "tr", Namespace = "")]
    public List<TableRow> RowData { get; set; }
}

public class TableRow
{
    [XmlElement("td")]
    public List<string> Data { get; set; }

    [XmlElement("th")]
    public List<string> Headers { get; set; }
}

Sample fiddle.

dbc
  • 104,963
  • 20
  • 228
  • 340