Go Down

Topic: simple XMLwriter library for Arduino (Read 2 times) previous topic - next topic

robtillaart

Nov 07, 2013, 08:11 pm Last Edit: Nov 07, 2013, 08:15 pm by robtillaart Reason: 1
Triggered by a post of Crossroads - http://forum.arduino.cc/index.php?topic=197251.0 - I wrote a simple library/class that helps to write XML output. Although still work in progress it seemed to me mature enough to post here so I can get feedback about all that is wrong.

Of course an example script to show how it can be used and its output.
Note that the data is made up or quite trivial.

Note the constructor can use any Print derived class, including Stream, Serial, etc (only tested Serial BTW).
XMLWriter XML(&Serial);

Code: (c++) [Select]
//
//    FILE: XMLWriterTest.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.01
// PURPOSE: make a simple XML generating lib
//    DATE: 2013-11-06
//     URL:
//
// Released to the public domain
//

#include <XMLWriter.h>

XMLWriter XML(&Serial);

char buffer[24];

void setup()
{
 Serial.begin(115200);

 XML.header();
 XML.comment("XMLWriterTest.ino\nThis is a demo of a simple XML lib for Arduino", true); // true means multi line here

 XML.tagOpen("Arduino", "42");

 XML.tagOpen("Ports");
 AnalogPorts("before");
 DigitalPorts();
 AnalogPorts("after");
 XML.tagClose();

 Weather();
 Weather2();

 XML.tagClose();
}

void Weather2()
{
 XML.comment("The weather in South Africa");
 for (int i=0; i<10; i++)
 {
   XML.tagStart("Weather");
   XML.tagField("Date", "20131106");
   XML.tagField("Time", "1:42");
   XML.tagField("Temp", "23.4");
   XML.tagField("Humi", "50%");
   XML.tagField("Rain", "10mm");
   XML.tagField("Sun", "40");
   XML.tagEnd();
 }
}

void Weather()
{
 XML.comment("The weather in Nebraska");
 XML.tagOpen("Weather");
 XML.writeNode("Date", "20131106");
 XML.writeNode("Time", "11:42");
 XML.writeNode("Temp", "23.4");
 XML.writeNode("Humi", "50%");
 XML.writeNode("Rain", "10mm");
 XML.writeNode("Sun", "40");
 XML.tagClose();
}

void AnalogPorts(char* name)
{
 XML.comment("The analog ports are multiplexed");
 XML.tagOpen("Analog", name);
 XML.writeNode("Analog0", itoa(analogRead(A0), buffer, 10));
 XML.writeNode("Analog1", analogRead(A1));
 XML.writeNode("Analog2", (5.0*analogRead(A2))/1023);      // default nr decimals float = 2
 XML.writeNode("Analog2", (5.0*analogRead(A2))/1023, 3);
 XML.tagClose();
}

void DigitalPorts()
{
 XML.comment("The digital ports are not multiplexed");
 XML.tagOpen("Digital");
 XML.writeNode("D1", itoa(digitalRead(1), buffer, 10));
 XML.writeNode("D13", digitalRead(13));
 XML.tagClose();
}

void loop()
{
}


The output looks as follows:
Code: (xml) [Select]

<?xml version="1.0" encoding="UTF-8"?>

<!--
XMLWriterTest.ino
This is a demo of a simple XML lib for Arduino
-->
<Arduino name="42">
 <Ports>

   <!-- The analog ports are multiplexed -->
   <Analog name="before">
     <Analog0>448</Analog0>
     <Analog1>362</Analog1>
     <Analog2>1.52</Analog2>
     <Analog2>1.584</Analog2>
   </Analog>

   <!-- The digital ports are not multiplexed -->
   <Digital>
     <D1>0</D1>
     <D13>0</D13>
   </Digital>

   <!-- The analog ports are multiplexed -->
   <Analog name="after">
     <Analog0>393</Analog0>
     <Analog1>428</Analog1>
     <Analog2>2.08</Analog2>
     <Analog2>1.994</Analog2>
   </Analog>
 </Ports>

 <!-- The weather in Nebraska -->
 <Weather>
   <Date>20131106</Date>
   <Time>11:42</Time>
   <Temp>23.4</Temp>
   <Humi>50%</Humi>
   <Rain>10mm</Rain>
   <Sun>40</Sun>
 </Weather>

 <!-- The weather in South Africa -->
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
 <Weather Date="20131106" Time="1:42" Temp="23.4" Humi="50%" Rain="10mm" Sun="40"/>
</Arduino>


Source see - https://github.com/RobTillaart/Arduino/tree/master/libraries/XMLWriter -

As always comments and remarks and improvements and ... are welcome.
(and no an XMLreader is not yet in the planning ;)
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

RbSCR

Nice !

Library is at your github-site I suppose ?

doughboy

How about adding check to escape the following characters

"   &quot;
'   &apos;
<   &lt;
>   &gt;
&   &amp;

or if not, to warn not to use those characters.

robtillaart


Nice !

Library is at your github-site I suppose ?


yep I added the link in the first post.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart


How about adding check to escape the following characters

"   &quot;
'   &apos;
<   &lt;
>   &gt;
&   &amp;

or if not, to warn not to use those characters.

Good point, might make the footprint larger, added to TODO
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

handling escapes looks quit good
- need more testing
- refactor code
- performance?
Code: (code/output) [Select]

void testEscapes()
{
  XML.comment("Test escape chars");
  XML.tagOpen("char");
  XML.writeNode("quote", "\"hello\"");
  XML.writeNode("apos", "\'hello\'");
  XML.writeNode("less", "5 < 33");
  XML.writeNode("great", "Peter > John");
  XML.writeNode("amp", " &array[0] ");
  XML.tagClose();
}

==>

  <!-- Test escape chars -->
  <char>
    <quote>&quot;hello&quot;</quote>
    <apos>&apos;hello&apos;</apos>
    <less>5 &lt; 33</less>
    <great>Peter &gt; John</great>
    <amp> &amp;array[0] </amp>
  </char>


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

#6
Nov 08, 2013, 05:12 pm Last Edit: Nov 09, 2013, 12:28 pm by robtillaart Reason: 1
upgraded to 0.1.02 - https://github.com/RobTillaart/Arduino/tree/master/libraries/XMLWriter -

+ added setIndentSize(uint8_t n);   0 = no indent, 2 = default; 4 looks OK too (spaces, no tabs)
+ corrected history
+ added escape() for special chars. - tip doughboy
+ added comments in the form of 'example' output in .h file
+ added some #defines to make code more readable.

as always comments remarks welcome.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

SamsGuamejy

hello guys,
I am not an expert in programming in arduino but I would like to make a log as XML stored on an SD card.

This is why I come to you to find out which parameter set instead of (&Serial) on line 14.
Otherwise if you have other ideas to parse XML,I'm interested.
The aim being to insert tags into an existing XML.

Example:
Code: [Select]
<?xml version="1.0" encoding="UTF-8"?>
<Log>
<element id="1" year="2014" month="1" day="1" hour="00" min="00" sec="00">
<sensor id="T1">20.0</sensor>
<sensor id="T2">20.0</sensor>
<sensor id="T3">20.0</sensor>
<sensor id="T4">20.0</sensor>
</element>
</Log>

To :
Code: [Select]
<?xml version="1.0" encoding="UTF-8"?>
<Log>
<element id="1" year="2014" month="1" day="1" hour="00" min="00" sec="00">
<sensor id="T1">20.0</sensor>
<sensor id="T2">20.0</sensor>
<sensor id="T3">20.0</sensor>
<sensor id="T4">20.0</sensor>
</element>
<element id="2" year="2014" month="1" day="1" hour="00" min="01" sec="00">
<sensor id="T1">20.0</sensor>
<sensor id="T2">20.0</sensor>
<sensor id="T3">20.0</sensor>
<sensor id="T4">20.0</sensor>
</element>
</Log>

robtillaart

Quote
This is why I come to you to find out which parameter set instead of (&Serial) on line 14.

Should be something that implements the Print class,
The File Class is derived from the Stream Class which is derived from the Print class so that should work (to certain level)

The XML writer class does not support appending directly. What I would try is the following. Let your application go to the end of the of the file on SD card, do a reverse search for the last </log> entry and start writing from that point. MIght work or ... not :)

Give it a try.


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up