- remove the spaccing between the elements
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Tue, 28 Oct 2008 08:57:13 +0000 (08:57 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Tue, 28 Oct 2008 08:57:13 +0000 (08:57 +0000)
- add xsd support to dump output
- change the argument "[--no-header|-n]" to [--header|-h {xsd,dtd}]
-- tobias.lindenmann 1und1.de

git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1637 a5681a0c-68f1-0310-ab6d-d61299d08faa

NEWS
doc/rrddump.pod
doc/rrdtool-dump.xsd [new file with mode: 0644]
src/rrd_dump.c
src/rrd_tool.c

diff --git a/NEWS b/NEWS
index 5497a67..8741b7b 100644 (file)
--- a/NEWS
+++ b/NEWS
 RRDTOOL NEWS
 ============
 
 RRDTOOL NEWS
 ============
 
-#####################################
-Major Changes between 1.2.x and 1.3.x
--------------------------------------
+##########################################
+Functional Changes between 1.3.x and 1.4.x
+------------------------------------------
 
 
-NEW Fast file access methods (Bernhard Fischer / Tobi Oetiker)
-----------------------------
-* introduced file-accessor functions rrd_read/rrd_seek/rrd_write
+RRDcached Accelerator
+---------------------
+tbd
 
 
-* implemented full mmap-based file access with madvise hints for
-  improved scalability, much reduced memory-footprint and much less
-  blocking while accessing the disk
-
-* implemented optional full file-descriptor access instead of FILE*
-  access
-
-NEW Graphing (Tobi Oetiker)
-------------
-* libart has been replaced by cairo/pango
-
-* pango markup is supported (--pango-markup)
-
-* full grid fitting
-
-* --graph-render-mode=mono for non anti aliased graphing
-
-* --font-render-mode=mono for non anti aliased fonts
-
-* fonts come through fontconfig, use the Pango font nameing scheme
-  -> 'Times 20' ... it is not possible to use truetype fonts
-  directly anymore.
-
-* Tabs are position independent.
-
-* TRENDNAN filter that ignores NAN values while calculating the
-  TREND data. (Timo Stripf)
-
-* --full-size-mode to specify the outer border of the image and not
-  just of the graphing canvas (Matthew Chambers)
-
-* TEXTALIGN command to alter default text alignment behavior
-
-* C API in-memory graphing with rrd_graph_v (Evan Miller)
-
-* draw dashed lines in graphs (Thomas Gutzler)
-
-* new interface graphv which returns information using the rrd_info
-  interface (Tobi Oetiker and Mark Plaksin)
-
-* improved horizontal grid. Have a bit more grid lines and y-axis
-  labels while keeping them far enough apart to not run into each
-  other.
-
-NEW Forecasting (Evan Miller)
----------------
-* the new MHWPREDICT consolidation function uses a variation of the
-  Holt-Winters method. It is a drop-in replacement for HWPREDICT,
-  and is better suited for data whose seasonal variations grow or
-  shrink in proportion to the average.
-
-* If you create an RRD with the new MHWPREDICT function, the
-  resulting rrd file will be version 0004 and can only be used in
-  rrdtool 1.3.
-
-Rewrites
---------
-* rrd_restore now uses libxml for parsing which makes things much
-  more tolerant towards xml variations. The old code could mostly
-  just parse the XML as it was output by rrdtool dump. See also:
-  the note at the bottom of this document. (by Florian octo
-  Forster)
-
-* rrd_update rewritten to make it more modular. Fixed two
-  longstanding HW bugs in the process (Evan Miller)
-
-Internationalization (Takao Fujiwara and Tobi Oetiker)
---------------------
-* The help output by rrdtool has been internationalized. There are
-  no real translations included with rrdtool yet, contributions are
-  welcome.
-
-* The internationalization will only be compiled if libintl and
-  friends are available on your system. Use the configure option
-  --disable-libintl if you want to disable this feature
-
-Language Bindings
------------------
-* ruby rrd_fetch will return step as a last property -- Mike Perham
-
-RRDtool dump / restore incompatibility
---------------------------------------
-* rrdtool dump 1.3 does emit completely legal XML. Basically this
-  means that it contains an XML header and a DOCTYPE definition.
-  Unfortunately this causes older versions of rrdtool restore to be
-  unhappy.
-
-* To restore a new dump with an old rrdtool restore version, either
-  remove the XML header and the doctype by hand (both on the first
-  line of the dump) or use rrdtool dump --no-header.
-
-
-######################################################################################
-Major Changes between 1.0.x and 1.2.x
-======================================================================================
-Graphing
---------
-
-* rewritten graphics generation based on libart.
-  - anti-aliased output
-  - alpha transparency support
-  - truetype fonts
-* additional graphics formats: EPS, PDF, SVG
-
-* extended multi-part documentation
-
-* VDEF support; define and use variables.  Find, and use, the
-  maximum rate seen by rrdtool; compute and show the average
-
-* Sliding window (trend) analysis
-  Compute a smoother average, for instance over the last 6 CDPs
-
-* percentile (95th or other)
-  Remove peaks, 95 percent of all rates are at or below the
-  returned value
-
-Logging
+RRDdump
 -------
 -------
-* a second logging interface: rrdtool updatev
-  Verbose updating of the database; show CPDs being created
-
-* Aberrant Behavior Detection with Holt-Winters Forecasting
-  Compare current data with expected data, detect and log when
-  the rates are outside expected levels
-
-* COMPUTE data type for artificial data-sources calculating their
-  input using RPN math and data from the other data-sources.
-Incompatibilities
------------------
-* Colons in COMMENT arguments to rrdtool graph must be escaped with a backslash
-
-* the --alt-y-mrtg option is gone or rather since 1.2.7 it is back but
-  without functionality.
-
-* In pipe mode, rrdtool answers with OK only if it was successful with the
-  command. Otherwhise the answer will be ERROR...
-
-
-Behind the Scenes
------------------
-* In order to support Holt-Winters and Calculated Datasources,
-  the rrdtool data format has changed. While the new version of rrdtool can
-  read files created with rrdtool 1.0.x. It is not possible to read files
-  created by rrdtool-1.2.x with rrdtool-1.0.x
-
-* External libraries are not included with rrdtool anymore. This is in line
-  with todays trend of using shared libraries everywhere. With the exception
-  of the cgi library most things required by rrdtool will be found on every recent
-  system.
-
-* Memory Mapped IO support for faster logging.
+* no more spaces in output
+* --no-header replaced with --header {xsd,dtd}
index c26d31b..52c68b6 100644 (file)
@@ -5,14 +5,14 @@ rrddump - dump the contents of an RRD to XML format
 =head1 SYNOPSIS
 
 B<rrdtool> B<dump> I<filename.rrd>
 =head1 SYNOPSIS
 
 B<rrdtool> B<dump> I<filename.rrd>
-S<[B<--no-header>|B<-n>]>
+S<[B<--header>|B<-h> {xsd,dtd}]>
 S<[B<--daemon> I<address>]>
 S<E<gt> I<filename.xml>>
 
 or 
 
 B<rrdtool> B<dump> I<filename.rrd> I<filename.xml>
 S<[B<--daemon> I<address>]>
 S<E<gt> I<filename.xml>>
 
 or 
 
 B<rrdtool> B<dump> I<filename.rrd> I<filename.xml>
-S<[B<--no-header>|B<-n>]>
+S<[B<--header>|B<-h> {xsd,dtd}]>
 S<[B<--daemon> I<address>]>
 
 =head1 DESCRIPTION
 S<[B<--daemon> I<address>]>
 
 =head1 DESCRIPTION
@@ -36,12 +36,9 @@ The name of the B<RRD> you want to dump.
 The (optional) filename that you want to write the XML output to.
 If not specified, the XML will be printed to stdout.
 
 The (optional) filename that you want to write the XML output to.
 If not specified, the XML will be printed to stdout.
 
-=item B<--no-header>|B<-n>
+=item B<--header>|B<-h> {xsd,dtd}
 
 
-In rrdtool 1.3, the dump function started producing correct xml-headers.
-Unfortunately the rrdtool restore function from the 1.2 series can not
-handle these headers. With this option you can supress the creatinon of
-the xml headers.
+Optionally rrdtool can add a xsd or dtd header to the dump output.
 
 =item B<--daemon> I<address>
 
 
 =item B<--daemon> I<address>
 
diff --git a/doc/rrdtool-dump.xsd b/doc/rrdtool-dump.xsd
new file mode 100644 (file)
index 0000000..22cd7ca
--- /dev/null
@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+       XML schema definition for the RRDTool dump output.
+
+       Author: 
+               Tobias Lindenmann <tobias.lindenmann at 1und1.de>
+-->
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
+       xmlns:ns="http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml" 
+       targetNamespace="http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml" 
+       elementFormDefault="qualified">
+       
+       <!-- Root element -->
+       <xsd:element name="rrd" type="ns:RrdType">
+               <!-- Check datasource name of unique. -->
+               <xsd:unique name="Ds.Name">
+                       <xsd:selector xpath="ns:ds/ns:name"/>
+                       <xsd:field xpath="."/>
+               </xsd:unique>
+       </xsd:element>
+       
+       <!-- Start of complexTypes -->
+       <xsd:complexType name="RrdType">
+               <xsd:sequence>
+                       <!-- RRD file version/RRD Archiv version number-->
+                       <xsd:element name="version" type="xsd:nonNegativeInteger"/>
+                       <!-- The primary RRD Archiv step in seconds.-->
+                       <xsd:element name="step" type="xsd:nonNegativeInteger"/>
+                       <!-- The unixtime from the last rrd_update.-->
+                       <xsd:element name="lastupdate" type="xsd:nonNegativeInteger"/>
+                       <xsd:element name="ds" type="ns:DsType" minOccurs="1" maxOccurs="unbounded"/>
+                       <!-- Round Robin Archive (rra). This is the place where the
+                            consolidated data points (cdp) get stored. The data is
+                            organized in rows (row) and columns (col). The Round Robin
+                            Archive got its name from the method data is stored in
+                            there. An RRD database can contain several Round Robin
+                            Archives. Each Round Robin Archive can have a different row
+                            spacing along the time axis (pdp_cnt) and a different
+                            consolidation function (cf) used to build its consolidated
+                            data points (cdp). -->
+                       <xsd:element name="rra" type="ns:RraType" minOccurs="1" maxOccurs="unbounded"/>
+               </xsd:sequence>
+       </xsd:complexType>
+       
+       <xsd:complexType name="DsType">
+               <xsd:sequence>
+                       <!-- The name of the data source. -->
+                       <xsd:element name="name" type="ns:DataSourceNameType"/>
+                       <!-- The Data Source Type (GAUGE, COUNTER, DERIVE, ABSOLUTE, COMPUTE)
+                            defines the applied to Build Primary Data Points from the 
+                            input provided by the data sources (ds). -->
+                       <xsd:element name="type" type="ns:DataSourceType"/>
+                       <!-- Chocie one groups of elements. -->
+                       <xsd:choice>
+                               <!-- Group with the elements min,max and heartbeat_min. -->
+                               <xsd:group ref="ns:Ds.NormalType"/>
+                               <!-- Group with the element cdef.-->
+                               <xsd:group ref="ns:Ds.CdefType"/>
+                       </xsd:choice>
+                       <xsd:element name="last_ds" type="ns:NumberWithUNKNType"/>
+                       <!-- Current value of the primary data point, this depends on the data source type. -->
+                       <xsd:element name="value" type="ns:LexicalNumberWithNaNType"/>
+                       <!-- How many seconds of the current 
+                                       * pdp value is unknown data?-->
+                       <xsd:element name="unknown_sec" type="xsd:nonNegativeInteger"/>
+               </xsd:sequence>
+       </xsd:complexType>
+
+       <xsd:complexType name="RraType">
+               <xsd:sequence>
+                       <!-- Consolidation Function (cf). An arbitrary Consolidation Function (cf)
+                            (averaging, min, max) is applied to the primary data points (pdp) to
+                            calculate the consolidated data point. -->
+                       <xsd:element name="cf" type="ns:ConsolidationFunctionType"/>
+                       <xsd:element name="pdp_per_row" type="xsd:nonNegativeInteger"/>
+                       <xsd:element name="params">
+                               <!-- Chocie one groups of elements. -->
+                               <xsd:complexType>
+                                       <xsd:choice>
+                                               <xsd:group ref="ns:Params.HwPredictType"/> 
+                                               <xsd:group ref="ns:Params.SeasonalType"/>
+                                               <xsd:group ref="ns:Params.FailuresType"/>
+                                               <xsd:group ref="ns:Params.DevPredictType"/>
+                                               <xsd:group ref="ns:Params.AvgMinMaxType"/>
+                                       </xsd:choice>
+                               </xsd:complexType>
+                       </xsd:element>
+                       <!-- Data prep area for cdp values -->
+                       <xsd:element name="cdp_prep" type="ns:CdpPrepType"/>
+                       <xsd:element name="database" type="ns:DatabaseType"/>
+               </xsd:sequence>
+       </xsd:complexType>
+
+       <xsd:complexType name="DatabaseType">
+               <xsd:sequence>
+                       <xsd:element name="row" type="ns:VType" minOccurs="1" maxOccurs="unbounded"/>
+               </xsd:sequence>
+       </xsd:complexType>
+
+       <xsd:complexType name="VType">
+               <xsd:sequence>
+                       <xsd:element name="v" type="ns:LexicalNumberWithNaNType" minOccurs="1" maxOccurs="unbounded"/>
+               </xsd:sequence> 
+       </xsd:complexType>
+
+       <xsd:complexType name="CdpPrepType">
+               <xsd:sequence>
+                       <xsd:element name="ds" minOccurs="1" maxOccurs="unbounded">
+                               <xsd:complexType>
+                                       <xsd:sequence>
+                                               <xsd:group ref="ns:Ds.Cdp"/>
+                                               <!-- Chocie one groups of elements. -->
+                                               <xsd:choice>
+                                                       <xsd:group ref="ns:Ds.Cdp.HwPredictType"/>
+                                                       <xsd:group ref="ns:Ds.Cdp.SeasonalType"/>
+                                                       <xsd:group ref="ns:Ds.Cdp.FailuresType"/>
+                                                       <xsd:group ref="ns:Ds.Cdp.AvgMinMaxType"/>
+                                               </xsd:choice>
+                                       </xsd:sequence>
+                               </xsd:complexType>
+                       </xsd:element>
+                </xsd:sequence>
+       </xsd:complexType>
+       <!-- End of complexTypes -->
+
+       <!-- Start of groups -->
+       <!-- Start of groups for the element rrd/ds. -->
+       <xsd:group name="Ds.NormalType">
+               <xsd:sequence>
+                       <!-- Minimum required heartbeat. A
+                                     * data source must provide input at
+                                     * least every ds_mrhb seconds,
+                                     * otherwise it is regarded dead and
+                                     * will be set to UNKNOWN -->
+                       <xsd:element name="minimal_heartbeat" type="xsd:integer"/>
+                       <!-- Min and max define the expected range values for data supplied by a data source. -->
+                       <xsd:element name="min" type="ns:LexicalNumberWithNaNType"/>
+                       <xsd:element name="max" type="ns:LexicalNumberWithNaNType"/>
+               </xsd:sequence>
+       </xsd:group>
+
+       <xsd:group name="Ds.CdefType">
+               <xsd:sequence>
+                       <xsd:element name="cdef" type="xsd:string"/>
+               </xsd:sequence>
+       </xsd:group>
+       <!-- End of groups for the element rrd/ds. -->
+       <!-- Start of groups for the element rrd/rra/cd_prep/ds. -->
+       <xsd:group name="Ds.Cdp.HwPredictType">
+               <xsd:sequence>
+                       <xsd:element name="intercept" type="ns:LexicalNumberWithNaNType"/>
+                       <xsd:element name="last_intercept" type="ns:LexicalNumberWithNaNType"/>
+                       <xsd:element name="slope" type="ns:LexicalNumberWithNaNType"/>
+                       <xsd:element name="last_slope" type="ns:LexicalNumberWithNaNType"/>
+                       <xsd:element name="nan_count" type="xsd:integer"/>
+                       <xsd:element name="last_nan_count" type="xsd:integer"/>
+               </xsd:sequence>
+       </xsd:group>
+
+       <xsd:group name="Ds.Cdp.SeasonalType">
+               <xsd:sequence>
+                       <xsd:element name="seasonal" type="ns:LexicalNumberWithNaNType"/>
+                       <xsd:element name="last_seasonal" type="ns:LexicalNumberWithNaNType"/>
+                       <xsd:element name="init_flag" type="xsd:integer"/>
+               </xsd:sequence>
+       </xsd:group>
+
+       <xsd:group name="Ds.Cdp.FailuresType">
+               <xsd:sequence>
+                       <!-- History failures message.-->
+                       <xsd:element name="history" type="xsd:string"/>
+               </xsd:sequence>
+       </xsd:group>
+
+       <xsd:group name="Ds.Cdp.AvgMinMaxType">
+               <xsd:sequence>
+                       <xsd:element name="value" type="ns:LexicalNumberWithNaNType"/>
+                       <xsd:element name="unknown_datapoints" type="xsd:integer"/>
+               </xsd:sequence>
+       </xsd:group>
+
+       <xsd:group name="Ds.Cdp">
+               <xsd:sequence>
+                       <xsd:element name="primary_value" type="ns:LexicalNumberWithNaNType"/>
+                       <xsd:element name="secondary_value" type="ns:LexicalNumberWithNaNType"/>
+               </xsd:sequence>
+       </xsd:group>
+       <!-- End of groups for the element cd_prep/ds. -->
+       <!-- Start of groups for the element params. -->
+       <xsd:group name="Params.HwPredictType">
+               <xsd:sequence>
+                        <xsd:element name="hw_alpha" type="ns:LexicalNumberType"/>
+                        <xsd:element name="hw_beta" type="ns:LexicalNumberType"/>
+                       <xsd:element name="dependent_rra_idx" type="xsd:integer"/>
+               </xsd:sequence>
+       </xsd:group>
+       
+       <xsd:group name="Params.SeasonalType">
+               <xsd:sequence>
+                        <xsd:element name="seasonal_gamma" type="ns:LexicalNumberType"/>
+                        <xsd:element name="seasonal_smooth_idx" type="xsd:integer"/>
+                       <xsd:element name="smoothing_window" type="ns:LexicalNumberType"/>
+                       <xsd:element name="dependent_rra_idx" type="xsd:integer"/>
+               </xsd:sequence>
+       </xsd:group>
+
+       <xsd:group name="Params.FailuresType">
+               <xsd:sequence>
+                        <xsd:element name="delta_pos" type="ns:LexicalNumberType"/>
+                        <xsd:element name="delta_neg" type="ns:LexicalNumberType"/>
+                       <xsd:element name="window_len" type="xsd:integer"/>
+                       <xsd:element name="failure_threshold" type="xsd:integer"/>
+               </xsd:sequence>
+       </xsd:group>
+
+       <xsd:group name="Params.DevPredictType">
+               <xsd:sequence>
+                       <xsd:element name="dependent_rra_idx" type="xsd:integer"/>
+               </xsd:sequence>
+       </xsd:group>
+
+       <xsd:group name="Params.AvgMinMaxType">
+               <xsd:sequence>
+                       <!-- The xfiles factor defines what part of a consolidation interval 
+                            may be made up from *UNKNOWN* data while the consolidated value
+                            is still regarded as known. It is given as the ratio of allowed
+                            *UNKNOWN* PDPs to the number of PDPs in the interval. Thus, it 
+                            ranges from 0 to 1 (exclusive). -->
+                       <xsd:element name="xff" type="ns:LexicalNumberType"/>
+               </xsd:sequence>
+       </xsd:group>
+       <!-- End of Groups for the element params. -->
+       <!-- End of groups -->
+       
+       <!-- Start of simpleTypes -->
+       <!-- Allowed data source types. -->
+       <!-- @see http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html-->
+       <xsd:simpleType name="DataSourceType">
+               <xsd:restriction base="xsd:string">
+                       <xsd:enumeration value="GAUGE"/>
+                       <xsd:enumeration value="COUNTER"/>
+                       <xsd:enumeration value="DERIVE"/>
+                       <xsd:enumeration value="ABSOLUTE"/>
+                       <xsd:enumeration value="COMPUTE"/>
+               </xsd:restriction>
+       </xsd:simpleType>
+       
+       <!-- A ds-name must be 1 to 19 characters long in the characters [a-zA-Z0-9_]. -->
+       <!-- @see http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html-->
+       <xsd:simpleType name="DataSourceNameType">
+               <xsd:restriction base="xsd:string">
+                       <xsd:pattern value="[a-zA-Z0-9_]{1,19}"/>
+               </xsd:restriction>
+       </xsd:simpleType>
+
+       <!-- Allowed consolidation function (cf). -->
+       <!-- @see http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html-->
+       <xsd:simpleType name="ConsolidationFunctionType">
+               <xsd:restriction base="xsd:string">
+                       <xsd:enumeration value="AVERAGE"/>
+                       <xsd:enumeration value="MIN"/>
+                       <xsd:enumeration value="MAX"/>
+                       <xsd:enumeration value="LAST"/>
+               </xsd:restriction>
+       </xsd:simpleType>
+       
+       <!-- Allowed a lexical number or the string "NaN".-->
+        <xsd:simpleType name="LexicalNumberWithNaNType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:pattern value="([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?|NaN)"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+
+       <!-- Allowed only a lexical number. -->
+        <xsd:simpleType name="LexicalNumberType">
+                <xsd:restriction base="xsd:string">
+                        <xsd:pattern value="[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?"/>
+                </xsd:restriction>
+        </xsd:simpleType>
+       
+       <!-- Allowed a number or the string "UNKN"  or "U". -->
+       <xsd:simpleType name="NumberWithUNKNType">
+               <xsd:restriction base="xsd:string">
+                       <xsd:pattern value="([\d]+|UNKN|U)"/>
+               </xsd:restriction>
+       </xsd:simpleType>
+       <!-- End of simpleTypes -->
+</xsd:schema>
index aa24882..9da8fd7 100644 (file)
@@ -52,7 +52,7 @@ extern char *tzname[2];
 static int rrd_dump_opt_r(
     const char *filename,
     char *outname,
 static int rrd_dump_opt_r(
     const char *filename,
     char *outname,
-    int opt_noheader)
+    int opt_header)
 {
     unsigned int i, ii, ix, iii = 0;
     time_t    now;
 {
     unsigned int i, ii, ix, iii = 0;
     time_t    now;
@@ -81,20 +81,29 @@ static int rrd_dump_opt_r(
         out_file = stdout;
     }
 
         out_file = stdout;
     }
 
-    if (!opt_noheader) {
+    if (opt_header == 1) {
         fputs("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n", out_file);
         fputs
             ("<!DOCTYPE rrd SYSTEM \"http://oss.oetiker.ch/rrdtool/rrdtool.dtd\">\n",
              out_file);
         fputs("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n", out_file);
         fputs
             ("<!DOCTYPE rrd SYSTEM \"http://oss.oetiker.ch/rrdtool/rrdtool.dtd\">\n",
              out_file);
+       fputs("<!-- Round Robin Database Dump -->\n", out_file);
+       fputs("<rrd>\n", out_file);
+    } else if (opt_header == 2) {
+       fputs("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n", out_file);
+       fputs("<!-- Round Robin Database Dump -->\n", out_file);
+       fputs("<rrd xmlns=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n", out_file);
+       fputs("\txsi:schemaLocation=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml http://oss.oetiker.ch/rrdtool/rrdtool-dump.xsd\">\n", out_file);
+    } else {
+       fputs("<!-- Round Robin Database Dump -->\n", out_file);
+       fputs("<rrd>\n", out_file);
     }
     }
-    fputs("<!-- Round Robin Database Dump -->", out_file);
-    fputs("<rrd>", out_file);
+
     if (atoi(rrd.stat_head->version) <= 3) {
     if (atoi(rrd.stat_head->version) <= 3) {
-        fprintf(out_file, "\t<version> %s </version>\n", RRD_VERSION3);
+        fprintf(out_file, "\t<version>%s</version>\n", RRD_VERSION3);
     } else {
     } else {
-        fprintf(out_file, "\t<version> %s </version>\n", RRD_VERSION);
+        fprintf(out_file, "\t<version>%s</version>\n", RRD_VERSION);
     }
     }
-    fprintf(out_file, "\t<step> %lu </step> <!-- Seconds -->\n",
+    fprintf(out_file, "\t<step>%lu</step> <!-- Seconds -->\n",
             rrd.stat_head->pdp_step);
 #if HAVE_STRFTIME
     localtime_r(&rrd.live_head->last_up, &tm);
             rrd.stat_head->pdp_step);
 #if HAVE_STRFTIME
     localtime_r(&rrd.live_head->last_up, &tm);
@@ -102,26 +111,26 @@ static int rrd_dump_opt_r(
 #else
 # error "Need strftime"
 #endif
 #else
 # error "Need strftime"
 #endif
-    fprintf(out_file, "\t<lastupdate> %lu </lastupdate> <!-- %s -->\n\n",
+    fprintf(out_file, "\t<lastupdate>%lu</lastupdate> <!-- %s -->\n\n",
             (unsigned long) rrd.live_head->last_up, somestring);
     for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
         fprintf(out_file, "\t<ds>\n");
             (unsigned long) rrd.live_head->last_up, somestring);
     for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
         fprintf(out_file, "\t<ds>\n");
-        fprintf(out_file, "\t\t<name> %s </name>\n", rrd.ds_def[i].ds_nam);
-        fprintf(out_file, "\t\t<type> %s </type>\n", rrd.ds_def[i].dst);
+        fprintf(out_file, "\t\t<name>%s</name>\n", rrd.ds_def[i].ds_nam);
+        fprintf(out_file, "\t\t<type>%s</type>\n", rrd.ds_def[i].dst);
         if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
             fprintf(out_file,
         if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
             fprintf(out_file,
-                    "\t\t<minimal_heartbeat> %lu </minimal_heartbeat>\n",
+                    "\t\t<minimal_heartbeat>%lu</minimal_heartbeat>\n",
                     rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);
             if (isnan(rrd.ds_def[i].par[DS_min_val].u_val)) {
                     rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);
             if (isnan(rrd.ds_def[i].par[DS_min_val].u_val)) {
-                fprintf(out_file, "\t\t<min> NaN </min>\n");
+                fprintf(out_file, "\t\t<min>NaN</min>\n");
             } else {
             } else {
-                fprintf(out_file, "\t\t<min> %0.10e </min>\n",
+                fprintf(out_file, "\t\t<min>%0.10e</min>\n",
                         rrd.ds_def[i].par[DS_min_val].u_val);
             }
             if (isnan(rrd.ds_def[i].par[DS_max_val].u_val)) {
                         rrd.ds_def[i].par[DS_min_val].u_val);
             }
             if (isnan(rrd.ds_def[i].par[DS_max_val].u_val)) {
-                fprintf(out_file, "\t\t<max> NaN </max>\n");
+                fprintf(out_file, "\t\t<max>NaN</max>\n");
             } else {
             } else {
-                fprintf(out_file, "\t\t<max> %0.10e </max>\n",
+                fprintf(out_file, "\t\t<max>%0.10e</max>\n",
                         rrd.ds_def[i].par[DS_max_val].u_val);
             }
         } else {        /* DST_CDEF */
                         rrd.ds_def[i].par[DS_max_val].u_val);
             }
         } else {        /* DST_CDEF */
@@ -129,25 +138,25 @@ static int rrd_dump_opt_r(
 
             rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),
                             rrd.ds_def, &str);
 
             rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),
                             rrd.ds_def, &str);
-            fprintf(out_file, "\t\t<cdef> %s </cdef>\n", str);
+            fprintf(out_file, "\t\t<cdef>%s</cdef>\n", str);
             free(str);
         }
         fprintf(out_file, "\n\t\t<!-- PDP Status -->\n");
             free(str);
         }
         fprintf(out_file, "\n\t\t<!-- PDP Status -->\n");
-        fprintf(out_file, "\t\t<last_ds> %s </last_ds>\n",
+        fprintf(out_file, "\t\t<last_ds>%s</last_ds>\n",
                 rrd.pdp_prep[i].last_ds);
         if (isnan(rrd.pdp_prep[i].scratch[PDP_val].u_val)) {
                 rrd.pdp_prep[i].last_ds);
         if (isnan(rrd.pdp_prep[i].scratch[PDP_val].u_val)) {
-            fprintf(out_file, "\t\t<value> NaN </value>\n");
+            fprintf(out_file, "\t\t<value>NaN</value>\n");
         } else {
         } else {
-            fprintf(out_file, "\t\t<value> %0.10e </value>\n",
+            fprintf(out_file, "\t\t<value>%0.10e</value>\n",
                     rrd.pdp_prep[i].scratch[PDP_val].u_val);
         }
                     rrd.pdp_prep[i].scratch[PDP_val].u_val);
         }
-        fprintf(out_file, "\t\t<unknown_sec> %lu </unknown_sec>\n",
+        fprintf(out_file, "\t\t<unknown_sec>%lu</unknown_sec>\n",
                 rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
 
         fprintf(out_file, "\t</ds>\n\n");
     }
 
                 rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
 
         fprintf(out_file, "\t</ds>\n\n");
     }
 
-    fputs("<!-- Round Robin Archives -->", out_file);
+    fputs("<!-- Round Robin Archives -->\n", out_file);
 
     rra_base = rrd_file->header_len;
     rra_next = rra_base;
 
     rra_base = rrd_file->header_len;
     rra_next = rra_base;
@@ -160,9 +169,9 @@ static int rrd_dump_opt_r(
         rra_next += (rrd.stat_head->ds_cnt
                      * rrd.rra_def[i].row_cnt * sizeof(rrd_value_t));
         fprintf(out_file, "\t<rra>\n");
         rra_next += (rrd.stat_head->ds_cnt
                      * rrd.rra_def[i].row_cnt * sizeof(rrd_value_t));
         fprintf(out_file, "\t<rra>\n");
-        fprintf(out_file, "\t\t<cf> %s </cf>\n", rrd.rra_def[i].cf_nam);
+        fprintf(out_file, "\t\t<cf>%s</cf>\n", rrd.rra_def[i].cf_nam);
         fprintf(out_file,
         fprintf(out_file,
-                "\t\t<pdp_per_row> %lu </pdp_per_row> <!-- %lu seconds -->\n\n",
+                "\t\t<pdp_per_row>%lu</pdp_per_row> <!-- %lu seconds -->\n\n",
                 rrd.rra_def[i].pdp_cnt,
                 rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);
         /* support for RRA parameters */
                 rrd.rra_def[i].pdp_cnt,
                 rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);
         /* support for RRA parameters */
@@ -170,46 +179,46 @@ static int rrd_dump_opt_r(
         switch (cf_conv(rrd.rra_def[i].cf_nam)) {
         case CF_HWPREDICT:
         case CF_MHWPREDICT:
         switch (cf_conv(rrd.rra_def[i].cf_nam)) {
         case CF_HWPREDICT:
         case CF_MHWPREDICT:
-            fprintf(out_file, "\t\t<hw_alpha> %0.10e </hw_alpha>\n",
+            fprintf(out_file, "\t\t<hw_alpha>%0.10e</hw_alpha>\n",
                     rrd.rra_def[i].par[RRA_hw_alpha].u_val);
                     rrd.rra_def[i].par[RRA_hw_alpha].u_val);
-            fprintf(out_file, "\t\t<hw_beta> %0.10e </hw_beta>\n",
+            fprintf(out_file, "\t\t<hw_beta>%0.10e</hw_beta>\n",
                     rrd.rra_def[i].par[RRA_hw_beta].u_val);
             fprintf(out_file,
                     rrd.rra_def[i].par[RRA_hw_beta].u_val);
             fprintf(out_file,
-                    "\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
+                    "\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
                     rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
             break;
         case CF_SEASONAL:
         case CF_DEVSEASONAL:
             fprintf(out_file,
                     rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
             break;
         case CF_SEASONAL:
         case CF_DEVSEASONAL:
             fprintf(out_file,
-                    "\t\t<seasonal_gamma> %0.10e </seasonal_gamma>\n",
+                    "\t\t<seasonal_gamma>%0.10e</seasonal_gamma>\n",
                     rrd.rra_def[i].par[RRA_seasonal_gamma].u_val);
             fprintf(out_file,
                     rrd.rra_def[i].par[RRA_seasonal_gamma].u_val);
             fprintf(out_file,
-                    "\t\t<seasonal_smooth_idx> %lu </seasonal_smooth_idx>\n",
+                    "\t\t<seasonal_smooth_idx>%lu</seasonal_smooth_idx>\n",
                     rrd.rra_def[i].par[RRA_seasonal_smooth_idx].u_cnt);
             if (atoi(rrd.stat_head->version) >= 4) {
                 fprintf(out_file,
                     rrd.rra_def[i].par[RRA_seasonal_smooth_idx].u_cnt);
             if (atoi(rrd.stat_head->version) >= 4) {
                 fprintf(out_file,
-                        "\t\t<smoothing_window> %0.10e </smoothing_window>\n",
+                        "\t\t<smoothing_window>%0.10e</smoothing_window>\n",
                         rrd.rra_def[i].par[RRA_seasonal_smoothing_window].
                         u_val);
             }
             fprintf(out_file,
                         rrd.rra_def[i].par[RRA_seasonal_smoothing_window].
                         u_val);
             }
             fprintf(out_file,
-                    "\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
+                    "\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
                     rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
             break;
         case CF_FAILURES:
                     rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
             break;
         case CF_FAILURES:
-            fprintf(out_file, "\t\t<delta_pos> %0.10e </delta_pos>\n",
+            fprintf(out_file, "\t\t<delta_pos>%0.10e</delta_pos>\n",
                     rrd.rra_def[i].par[RRA_delta_pos].u_val);
                     rrd.rra_def[i].par[RRA_delta_pos].u_val);
-            fprintf(out_file, "\t\t<delta_neg> %0.10e </delta_neg>\n",
+            fprintf(out_file, "\t\t<delta_neg>%0.10e</delta_neg>\n",
                     rrd.rra_def[i].par[RRA_delta_neg].u_val);
                     rrd.rra_def[i].par[RRA_delta_neg].u_val);
-            fprintf(out_file, "\t\t<window_len> %lu </window_len>\n",
+            fprintf(out_file, "\t\t<window_len>%lu</window_len>\n",
                     rrd.rra_def[i].par[RRA_window_len].u_cnt);
             fprintf(out_file,
                     rrd.rra_def[i].par[RRA_window_len].u_cnt);
             fprintf(out_file,
-                    "\t\t<failure_threshold> %lu </failure_threshold>\n",
+                    "\t\t<failure_threshold>%lu</failure_threshold>\n",
                     rrd.rra_def[i].par[RRA_failure_threshold].u_cnt);
             /* fall thru */
         case CF_DEVPREDICT:
             fprintf(out_file,
                     rrd.rra_def[i].par[RRA_failure_threshold].u_cnt);
             /* fall thru */
         case CF_DEVPREDICT:
             fprintf(out_file,
-                    "\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
+                    "\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
                     rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
             break;
         case CF_AVERAGE:
                     rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
             break;
         case CF_AVERAGE:
@@ -217,7 +226,7 @@ static int rrd_dump_opt_r(
         case CF_MINIMUM:
         case CF_LAST:
         default:
         case CF_MINIMUM:
         case CF_LAST:
         default:
-            fprintf(out_file, "\t\t<xff> %0.10e </xff>\n",
+            fprintf(out_file, "\t\t<xff>%0.10e</xff>\n",
                     rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
             break;
         }
                     rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
             break;
         }
@@ -236,10 +245,10 @@ static int rrd_dump_opt_r(
                                  + ii].scratch[CDP_primary_val].u_val;
             if (isnan(value)) {
                 fprintf(out_file,
                                  + ii].scratch[CDP_primary_val].u_val;
             if (isnan(value)) {
                 fprintf(out_file,
-                        "\t\t\t<primary_value> NaN </primary_value>\n");
+                        "\t\t\t<primary_value>NaN</primary_value>\n");
             } else {
                 fprintf(out_file,
             } else {
                 fprintf(out_file,
-                        "\t\t\t<primary_value> %0.10e </primary_value>\n",
+                        "\t\t\t<primary_value>%0.10e</primary_value>\n",
                         value);
             }
             value =
                         value);
             }
             value =
@@ -247,10 +256,10 @@ static int rrd_dump_opt_r(
                              ii].scratch[CDP_secondary_val].u_val;
             if (isnan(value)) {
                 fprintf(out_file,
                              ii].scratch[CDP_secondary_val].u_val;
             if (isnan(value)) {
                 fprintf(out_file,
-                        "\t\t\t<secondary_value> NaN </secondary_value>\n");
+                        "\t\t\t<secondary_value>NaN</secondary_value>\n");
             } else {
                 fprintf(out_file,
             } else {
                 fprintf(out_file,
-                        "\t\t\t<secondary_value> %0.10e </secondary_value>\n",
+                        "\t\t\t<secondary_value>%0.10e</secondary_value>\n",
                         value);
             }
             switch (cf_conv(rrd.rra_def[i].cf_nam)) {
                         value);
             }
             switch (cf_conv(rrd.rra_def[i].cf_nam)) {
@@ -260,29 +269,29 @@ static int rrd_dump_opt_r(
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_hw_intercept].u_val;
                 if (isnan(value)) {
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_hw_intercept].u_val;
                 if (isnan(value)) {
-                    fprintf(out_file, "\t\t\t<intercept> NaN </intercept>\n");
+                    fprintf(out_file, "\t\t\t<intercept>NaN</intercept>\n");
                 } else {
                     fprintf(out_file,
                 } else {
                     fprintf(out_file,
-                            "\t\t\t<intercept> %0.10e </intercept>\n", value);
+                            "\t\t\t<intercept>%0.10e</intercept>\n", value);
                 }
                 value =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_hw_last_intercept].u_val;
                 if (isnan(value)) {
                     fprintf(out_file,
                 }
                 value =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_hw_last_intercept].u_val;
                 if (isnan(value)) {
                     fprintf(out_file,
-                            "\t\t\t<last_intercept> NaN </last_intercept>\n");
+                            "\t\t\t<last_intercept>NaN</last_intercept>\n");
                 } else {
                     fprintf(out_file,
                 } else {
                     fprintf(out_file,
-                            "\t\t\t<last_intercept> %0.10e </last_intercept>\n",
+                            "\t\t\t<last_intercept>%0.10e</last_intercept>\n",
                             value);
                 }
                 value =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_hw_slope].u_val;
                 if (isnan(value)) {
                             value);
                 }
                 value =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_hw_slope].u_val;
                 if (isnan(value)) {
-                    fprintf(out_file, "\t\t\t<slope> NaN </slope>\n");
+                    fprintf(out_file, "\t\t\t<slope>NaN</slope>\n");
                 } else {
                 } else {
-                    fprintf(out_file, "\t\t\t<slope> %0.10e </slope>\n",
+                    fprintf(out_file, "\t\t\t<slope>%0.10e</slope>\n",
                             value);
                 }
                 value =
                             value);
                 }
                 value =
@@ -290,22 +299,22 @@ static int rrd_dump_opt_r(
                                  ii].scratch[CDP_hw_last_slope].u_val;
                 if (isnan(value)) {
                     fprintf(out_file,
                                  ii].scratch[CDP_hw_last_slope].u_val;
                 if (isnan(value)) {
                     fprintf(out_file,
-                            "\t\t\t<last_slope> NaN </last_slope>\n");
+                            "\t\t\t<last_slope>NaN</last_slope>\n");
                 } else {
                     fprintf(out_file,
                 } else {
                     fprintf(out_file,
-                            "\t\t\t<last_slope> %0.10e </last_slope>\n",
+                            "\t\t\t<last_slope>%0.10e</last_slope>\n",
                             value);
                 }
                 ivalue =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_null_count].u_cnt;
                             value);
                 }
                 ivalue =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_null_count].u_cnt;
-                fprintf(out_file, "\t\t\t<nan_count> %lu </nan_count>\n",
+                fprintf(out_file, "\t\t\t<nan_count>%lu</nan_count>\n",
                         ivalue);
                 ivalue =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_last_null_count].u_cnt;
                 fprintf(out_file,
                         ivalue);
                 ivalue =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_last_null_count].u_cnt;
                 fprintf(out_file,
-                        "\t\t\t<last_nan_count> %lu </last_nan_count>\n",
+                        "\t\t\t<last_nan_count>%lu</last_nan_count>\n",
                         ivalue);
                 break;
             case CF_SEASONAL:
                         ivalue);
                 break;
             case CF_SEASONAL:
@@ -314,9 +323,9 @@ static int rrd_dump_opt_r(
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_hw_seasonal].u_val;
                 if (isnan(value)) {
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_hw_seasonal].u_val;
                 if (isnan(value)) {
-                    fprintf(out_file, "\t\t\t<seasonal> NaN </seasonal>\n");
+                    fprintf(out_file, "\t\t\t<seasonal>NaN</seasonal>\n");
                 } else {
                 } else {
-                    fprintf(out_file, "\t\t\t<seasonal> %0.10e </seasonal>\n",
+                    fprintf(out_file, "\t\t\t<seasonal>%0.10e</seasonal>\n",
                             value);
                 }
                 value =
                             value);
                 }
                 value =
@@ -324,16 +333,16 @@ static int rrd_dump_opt_r(
                                  ii].scratch[CDP_hw_last_seasonal].u_val;
                 if (isnan(value)) {
                     fprintf(out_file,
                                  ii].scratch[CDP_hw_last_seasonal].u_val;
                 if (isnan(value)) {
                     fprintf(out_file,
-                            "\t\t\t<last_seasonal> NaN </last_seasonal>\n");
+                            "\t\t\t<last_seasonal>NaN</last_seasonal>\n");
                 } else {
                     fprintf(out_file,
                 } else {
                     fprintf(out_file,
-                            "\t\t\t<last_seasonal> %0.10e </last_seasonal>\n",
+                            "\t\t\t<last_seasonal>%0.10e</last_seasonal>\n",
                             value);
                 }
                 ivalue =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_init_seasonal].u_cnt;
                             value);
                 }
                 ivalue =
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_init_seasonal].u_cnt;
-                fprintf(out_file, "\t\t\t<init_flag> %lu </init_flag>\n",
+                fprintf(out_file, "\t\t\t<init_flag>%lu</init_flag>\n",
                         ivalue);
                 break;
             case CF_DEVPREDICT:
                         ivalue);
                 break;
             case CF_DEVPREDICT:
@@ -366,13 +375,13 @@ static int rrd_dump_opt_r(
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_val].u_val;
                 if (isnan(value)) {
                     rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                  ii].scratch[CDP_val].u_val;
                 if (isnan(value)) {
-                    fprintf(out_file, "\t\t\t<value> NaN </value>\n");
+                    fprintf(out_file, "\t\t\t<value>NaN</value>\n");
                 } else {
                 } else {
-                    fprintf(out_file, "\t\t\t<value> %0.10e </value>\n",
+                    fprintf(out_file, "\t\t\t<value>%0.10e</value>\n",
                             value);
                 }
                 fprintf(out_file,
                             value);
                 }
                 fprintf(out_file,
-                        "\t\t\t<unknown_datapoints> %lu </unknown_datapoints>\n",
+                        "\t\t\t<unknown_datapoints>%lu</unknown_datapoints>\n",
                         rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                      ii].scratch[CDP_unkn_pdp_cnt].u_cnt);
                 break;
                         rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                      ii].scratch[CDP_unkn_pdp_cnt].u_cnt);
                 break;
@@ -410,9 +419,9 @@ static int rrd_dump_opt_r(
             for (iii = 0; iii < rrd.stat_head->ds_cnt; iii++) {
                 rrd_read(rrd_file, &my_cdp, sizeof(rrd_value_t) * 1);
                 if (isnan(my_cdp)) {
             for (iii = 0; iii < rrd.stat_head->ds_cnt; iii++) {
                 rrd_read(rrd_file, &my_cdp, sizeof(rrd_value_t) * 1);
                 if (isnan(my_cdp)) {
-                    fprintf(out_file, "<v> NaN </v>");
+                    fprintf(out_file, "<v>NaN</v>");
                 } else {
                 } else {
-                    fprintf(out_file, "<v> %0.10e </v>", my_cdp);
+                    fprintf(out_file, "<v>%0.10e</v>", my_cdp);
                 };
             }
             fprintf(out_file, "</row>\n");
                 };
             }
             fprintf(out_file, "</row>\n");
@@ -441,7 +450,12 @@ int rrd_dump(
     char **argv)
 {
     int       rc;
     char **argv)
 {
     int       rc;
-    int       opt_noheader = 0;
+    /** 
+     * 0 = no header
+     * 1 = dtd header
+     * 2 = xsd header
+     */
+    int       opt_header = 0;
     char     *opt_daemon = NULL;
 
     /* init rrd clean */
     char     *opt_daemon = NULL;
 
     /* init rrd clean */
@@ -454,11 +468,11 @@ int rrd_dump(
         int       option_index = 0;
         static struct option long_options[] = {
             {"daemon", required_argument, 0, 'd'},
         int       option_index = 0;
         static struct option long_options[] = {
             {"daemon", required_argument, 0, 'd'},
-            {"no-header", no_argument, 0, 'n'},
+            {"header", required_argument, 0, 'h'},
             {0, 0, 0, 0}
         };
 
             {0, 0, 0, 0}
         };
 
-        opt = getopt_long(argc, argv, "d:n", long_options, &option_index);
+        opt = getopt_long(argc, argv, "d:h:", long_options, &option_index);
 
         if (opt == EOF)
             break;
 
         if (opt == EOF)
             break;
@@ -475,12 +489,16 @@ int rrd_dump(
             }
             break;
 
             }
             break;
 
-        case 'n':
-            opt_noheader = 1;
-            break;
+        case 'h':
+          if (strcmp(optarg, "dtd") == 0) {
+               opt_header = 1;
+          } else if (strcmp(optarg, "xsd") == 0) {
+               opt_header = 2;
+          }
+          break;
 
         default:
 
         default:
-            rrd_set_error("usage rrdtool %s [--no-header|-n] "
+            rrd_set_error("usage rrdtool %s [--header|-h {xsd,dtd}] "
                           "file.rrd [file.xml]", argv[0]);
             return (-1);
             break;
                           "file.rrd [file.xml]", argv[0]);
             return (-1);
             break;
@@ -488,7 +506,7 @@ int rrd_dump(
     }                   /* while (42) */
 
     if ((argc - optind) < 1 || (argc - optind) > 2) {
     }                   /* while (42) */
 
     if ((argc - optind) < 1 || (argc - optind) > 2) {
-        rrd_set_error("usage rrdtool %s [--no-header|-n] "
+        rrd_set_error("usage rrdtool %s [--header|-h {xsd,dtd}] "
                       "file.rrd [file.xml]", argv[0]);
         return (-1);
     }
                       "file.rrd [file.xml]", argv[0]);
         return (-1);
     }
@@ -498,9 +516,9 @@ int rrd_dump(
     if (rc) return (rc);
 
     if ((argc - optind) == 2) {
     if (rc) return (rc);
 
     if ((argc - optind) == 2) {
-        rc = rrd_dump_opt_r(argv[optind], argv[optind + 1], opt_noheader);
+        rc = rrd_dump_opt_r(argv[optind], argv[optind + 1], opt_header);
     } else {
     } else {
-        rc = rrd_dump_opt_r(argv[optind], NULL, opt_noheader);
+        rc = rrd_dump_opt_r(argv[optind], NULL, opt_header);
     }
 
     return rc;
     }
 
     return rc;
index 4da8019..051631c 100644 (file)
@@ -70,7 +70,8 @@ void PrintUsage(
 
     const char *help_dump =
         N_("* dump - dump an RRD to XML\n\n"
 
     const char *help_dump =
         N_("* dump - dump an RRD to XML\n\n"
-           "\trrdtool dump filename.rrd >filename.xml\n\n");
+           "\trrdtool dump filename.rrd >filename.xml\n"
+           "\t\t[--header|-h {xsd,dtd}]\n\n");
 
     const char *help_info =
         N_("* info - returns the configuration and status of the RRD\n\n"
 
     const char *help_info =
         N_("* info - returns the configuration and status of the RRD\n\n"