1

I'm trying to serialize to the following XML structure using the XmlWriter in C#:

<userProfiles>
  <groupId>12345</groupId>
  <profile>
    <name>test 1</name>
    <id>10000</id>
    <ns:userPerformance>
      <ns:type>yearly</ns:type>
      <ns:values>            
          <ns:value>
            <ns:start>start time</ns:start>
            <ns:end>end time</ns:end>
            <ns:value>6712736</ns:value>
          </ns:value>
      </ns:values>
    </ns:userPerformance>
  </profile>

  <profile>
    <name>test 2</name>
    <id>20000</id>
    <ns:userPerformance>
      <ns:type>yearly</ns:type>
      <ns:values>            
          <ns:value>
            <ns:start>start time</ns:start>
            <ns:end>end time</ns:end>
            <ns:value>712367</ns:value>
          </ns:value>
          <ns:value>
            <ns:start>start time</ns:start>
            <ns:end>end time</ns:end>
            <ns:value>54656</ns:value>
          </ns:value>
      </ns:values>
    </ns:userPerformance>
  </profile>
</userProfiles>

I'm trying to populate the userPerformance elements. I know that I have to iterate between two dates to create the ns:values, but how can I set which element would be the start element so that I populate my ns:values? Here is what I have so far!

    var xml = new XmlTextWriter(new StringWriter());

    xml.WriteStartDocument();
    xml.WriteStartElement("userProfiles");
    xml.WriteElementString("groupId", "1");

    foreach (var profile in profiles)
    {
        xml.WriteStartElement("profile");
        {
            xml.WriteElementString("name", "test 1");
            xml.WriteElementString("id", "10000");

            // assume that I have the proper allDays as a List of DateTime
            foreach(var days in allDays)
            {
                // What will be my StartElement?
                xml.WriteStartElement("userPerformance");
            }
        }
    }

If I have userPerformance as the StartElement inside the inner loop where I iterate over the days, I might end up having it multiple times for each of the day. How can I avoid it?

joesan
  • 13,963
  • 27
  • 95
  • 232
  • 1
    I would recommend going down another path: generate C# classes from your XML ( using xsd.exe ) then build your model in code and XML serialize it with a one-liner. See http://stackoverflow.com/questions/4203540/generate-c-sharp-class-from-xml – Jochen van Wylick Feb 03 '15 at 16:24
  • No I would refrain from using generated classes. – joesan Feb 03 '15 at 16:30
  • what's your motivation? – Jochen van Wylick Feb 03 '15 at 16:31
  • I do not want to have a bunch of generated code which I might not need. The xml above is a subset of a big xml file. This xml above would still pass the schema validation against the xsd for the big xml. – joesan Feb 03 '15 at 16:33
  • OK - fine by me. I think the sequence in the XML is the same as the sequence with which you call WriteStartElement. So I think you need to sort the allDays in the way you want them to appear in the XML. – Jochen van Wylick Feb 03 '15 at 16:36
  • I did not get that! Could you please post that as a solution? – joesan Feb 03 '15 at 16:36

3 Answers3

1

Try this:

xml.WriteStartDocument();
xml.WriteStartElement("userProfiles");
xml.WriteElementString("groupId", "1");

foreach (var profile in profiles)
{
    xml.WriteStartElement("profile");
    xml.WriteElementString("name", "test 1");
    xml.WriteElementString("id", "10000");
    xml.WriteStartElement("userPerformance");

    xml.WriteElementString("type", "yearly");
    // assume that I have the proper allDays as a List of DateTime
    foreach (var days in allDays)
    {
        // What will be my StartElement?
        xml.WriteStartElement("values");
        xml.WriteElementString("start", DateTime.Now.ToString());
        xml.WriteElementString("end", DateTime.Now.ToString());
        xml.WriteElementString("value", "0815");
        xml.WriteEndElement();
    }
    xml.WriteEndElement();
    xml.WriteEndElement();
}

xml.WriteEndElement();
PinBack
  • 2,499
  • 12
  • 16
0

I think the sequence in the XML is the same as the sequence with which you call WriteStartElement. So I think you need to sort the allDays in the way you want them to appear in the XML.

Jochen van Wylick
  • 5,303
  • 4
  • 42
  • 64
0

An other way could be to do it this way: (this code is an example which may not compile)

var userProfiles = new XElement("userProfiles");
foreach (var currentProfile in profiles)
{
    var profile = new XElement("profile");
    profile.Add(new XElement("name", currentProfile.name));
    profile.Add(new XElement("id", currentProfile.id));

        var performance = new XElement("performance");
        performance.Add(new XElement("type", "yearly"));

        var values = new XElement("values");

        foreach(var days in allDays)
        {
            var value = new XElement("value");
            value.Add(new XElement("start", days.start));
            value.Add(new XElement("end", days.end));
            value.Add(new XElement("value", days.value));
            values.Add(value);
        }

        performance.Add(values);

        profile.Add(performance);

    userProfiles.Add(profile);
}
Abyte0
  • 852
  • 8
  • 9
  • I want to avoid using XElement and only use XmlWriter! – joesan Feb 03 '15 at 16:42
  • userProfiles.Save(YOUR_XMLWRITER_HERE); according to this link : https://msdn.microsoft.com/en-us/library/bb359357%28v=vs.110%29.aspx – Abyte0 Feb 03 '15 at 19:17