<?xml version="1.0" standalone="yes"?>
<!--
Copyright (c) 2004 Russell E. Gibson
email: russg@rnstech.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
$Id: xcgtempl.xml.html,v 1.1 2004/11/23 09:35:56 rnstech Exp $
-->
<generator>
<!--
****************************************************************************************************************
* HEADER *
* This section contains all the header related sections *
****************************************************************************************************************
-->
<!--header *************************************************************************************-->
<file name="<file>/<root-c>.hpp">
<content type="template">license</content>
<content type="template">header start</content>
<content type="template">header elements</content>
<content type="template">header end</content>
</file>
<!--license (used through out) *****************************************************************-->
<template name="license" type="inline">
<content>
<![CDATA[
//
// Copyright (c) 2004 Russell E. Gibson
// email: russg@rnstech.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is furnished
// to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
]]>
</content>
</template>
<!--header start *******************************************************************************-->
<template name="header start" type="inline">
<content>
<![CDATA[
#ifndef __<root-C>_HPP__
#define __<root-C>_HPP__
#include <string>
#include <vector>
#include <libxml/parser.h>
#include <libxml/xmlwriter.h>
namespace <root>
{
]]>
</content>
</template>
<!--header elements ****************************************************************************-->
<template name="header elements" type="elements" order="tree">
<content type="template">header elements start</content>
<content type="template">header elements attributes</content>
<content type="template">header elements children</content>
<content type="template">header elements end</content>
</template>
<!--header elements start **********************************************************************-->
<template name="header elements start" type="inline">
<content>
<![CDATA[
//=============================================================================
// Element '<element>' encapsulation
]]>
</content>
<content if="isNotSingle">
<![CDATA[
typedef std::vector<class <element-vc>> <element-vC>_VECTOR;
]]>
</content>
<content>
<![CDATA[
class <element-vc>
{
//-------------------------------------------------------------------------
// Construction & operators
public:
<element-vc>();
<element-vc>(const char* f);
<element-vc>(xmlNodePtr n);
<element-vc>(const <element-vc>& c);
virtual ~<element-vc>() throw ();
<element-vc>& operator=(const <element-vc>& r);
]]>
</content>
</template>
<!--header elements attributes *****************************************************************-->
<template name="header elements attributes" type="attributes" order="alpha">
<content>
<![CDATA[
//-------------------------------------------------------------------------
// Attribute <attribute>
public:
const std::string& <attribute-vt>() const;
void <attribute-vt>(const char* <a>);
private:
std::string _<attribute-Vt>;
]]>
</content>
</template>
<!--header elements children *******************************************************************-->
<template name="header elements children" type="children">
<content if="childIsSingle">
<![CDATA[
//-------------------------------------------------------------------------
// Child element <child>
public:
<child-vc>& <child-vt>();
const <child-vc>& <child-vt>() const;
private:
<child-vc> _<child-vt>;
]]>
</content>
<content if="childIsNotSingle">
<![CDATA[
//-------------------------------------------------------------------------
// Child element <child>
public:
<child-vC>_VECTOR& <child-vtp>();
const <child-vC>_VECTOR& <child-vtp>() const;
private:
<child-vC>_VECTOR _<child-vtp>;
]]>
</content>
</template>
<!--header elements end ************************************************************************-->
<template name="header elements end" type="inline">
<content>
<![CDATA[
//-------------------------------------------------------------------------
// Read from node
public:
void read(xmlNodePtr p);
]]>
</content>
<content if="hasValue">
<![CDATA[
//-------------------------------------------------------------------------
// Value of this element
private:
typedef std::pair<bool, std::string> VALUE; // (element here?, text)
typedef std::vector<VALUE> VALUES;
public:
VALUES& values();
const VALUES& values() const;
void value(std::string& v) const;
private:
VALUES _values;
]]>
</content>
<content>
<![CDATA[
//-------------------------------------------------------------------------
// Write to file or node
public:
void write(xmlTextWriterPtr w) const;
]]>
</content>
<content if="writeToFile">
<![CDATA[
void write(const char* f, bool i = true, const char* t = "\t") const;
]]>
</content>
<content>
<![CDATA[
};
]]>
</content>
<content if="notLastElement">
<![CDATA[
]]>
</content>
</template>
<!--header end *********************************************************************************-->
<template name="header end" type="inline">
<content>
<![CDATA[
}
#include "<root>.inl"
#endif // __<root-C>_HPP__
]]>
</content>
</template>
<!--
****************************************************************************************************************
* INLINE SOURCE *
* This section all the inline related sections. *
****************************************************************************************************************
-->
<!--inline *************************************************************************************-->
<file name="<file>/<root-c>.inl">
<content type="template">license</content>
<content type="template">inline start</content>
<content type="template">inline elements</content>
<content type="template">inline end</content>
</file>
<!--inline start *******************************************************************************-->
<template name="inline start" type="inline">
<content>
<![CDATA[
#ifndef __<root-C>_INL__
#define __<root-C>_INL__
namespace <root>
{
]]>
</content>
</template>
<!--inline elements ****************************************************************************-->
<template name="inline elements" type="elements" order="alpha">
<content type="template">inline elements start</content>
<content type="template">inline elements attributes</content>
<content type="template">inline elements children</content>
<content type="template">inline elements end</content>
</template>
<!--inline end *********************************************************************************-->
<template name="inline end" type="inline">
<content>
<![CDATA[
}
#endif // __<root-C>_INL__
]]>
</content>
</template>
<!--inline elements start **********************************************************************-->
<template name="inline elements start" type="inline">
<content>
<![CDATA[
//=============================================================================
// class <element-vc> inline implementation
inline <element-vc>::<element-vc>()
{
}
inline <element-vc>::<element-vc>(const <element-vc>& r)
{
*this = r;
}
inline <element-vc>::~<element-vc>() throw ()
{
}
]]>
</content>
</template>
<!--inline elements attributes *****************************************************************-->
<template name="inline elements attributes" type="attributes" order="alpha">
<content>
<![CDATA[
inline const std::string& <element-vc>::<attribute-vt>() const
{
return _<attribute-Vt>;
}
inline void <element-vc>::<attribute-vt>(const char* <a-t>)
{
_<attribute-Vt> = <a-t>;
}
]]>
</content>
</template>
<!--inline elements children *******************************************************************-->
<template name="inline elements children" type="children">
<content if="childIsSingle">
<![CDATA[
inline <child-vc>& <element-vc>::<child-vt>()
{
return _<child-vt>;
}
inline const <child-vc>& <element-vc>::<child-vt>() const
{
return _<child-vt>;
}
]]>
</content>
<content if="childIsNotSingle">
<![CDATA[
inline <child-vC>_VECTOR& <element-vc>::<child-vtp>()
{
return _<child-vtp>;
}
inline const <child-vC>_VECTOR& <element-vc>::<child-vtp>() const
{
return _<child-vtp>;
}
]]>
</content>
</template>
<!--inline elements end ************************************************************************-->
<template name="inline elements end" type="inline">
<content if="hasValue">
<![CDATA[
inline <element-vc>::VALUES& <element-vc>::values()
{
return _values;
}
inline const <element-vc>::VALUES& <element-vc>::values() const
{
return _values;
}
]]>
</content>
<content if="notLastElement">
<![CDATA[
]]>
</content>
</template>
<!--
****************************************************************************************************************
* SOURCE *
* This section contains all the sections related to source. *
****************************************************************************************************************
-->
<!--source *************************************************************************************-->
<file name="<file>/<root-c>.cpp">
<content type="template">license</content>
<content type="template">source start</content>
<content type="template">source elements</content>
</file>
<!--source start *******************************************************************************-->
<template name="source start" type="inline">
<content>
<![CDATA[
#include <algorithm>
#include <locale>
#include "<root>.hpp"
using namespace <root>;
//=============================================================================
// Local functions
namespace
{
// Called on reading to clear out whitespace and control characters from
// an XML_TEXT_NODE. The idea is to get the actual value of an element
// rather than the whitespace used in formatting the file its in.
xmlChar* trim(xmlChar* t)
{
std::locale l = std::locale();
while (*t && (std::iscntrl(*t, l) || *t == ' '))
++t;
return t;
}
// Called on reading to clear out whitespace and control characters from
// an XML_CDATA_SECTION_NODE. The idea is to get the actual value of an
// unless its followed by an end of line first.
xmlChar* trim_cdata(xmlChar* t)
{
std::locale l = std::locale();
xmlChar* lt = t;
while (*t)
{
// Found end of line?
if (*t == '\r')
{
// Skip it
++t;
// Is it followed by linefeed?
if (*t != '\n')
return t;
// Yes, so skip it too
++t;
return t;
}
// Found linefed (unix eol)?
if (*t == '\n')
return ++t;
// Is it not a whitespace or control char?
if (!std::iscntrl(*t, l) && !std::isspace(*t, l))
return lt;
++t;
}
return t;
}
// Functor to call write on each child element
template <typename T>
class writer
{
public:
writer(xmlTextWriterPtr w)
:
_w(w)
{
}
void operator()(const T& t)
{
t.write(_w);
}
private:
xmlTextWriterPtr _w;
};
}
]]>
</content>
</template>
<!--source elements ****************************************************************************-->
<template name="source elements" type="elements" order="alpha">
<!--source elements ********************************************************-->
<content type="template">source elements start</content>
<!--source elements operator= **********************************************-->
<content type="template">source elements operator= start</content>
<content type="template">source elements operator= attributes</content>
<content type="template">source elements operator= children</content>
<content type="template">source elements operator= end</content>
<!--source elements read ***************************************************-->
<content type="template">source elements read start</content>
<content type="template">source elements read attributes</content>
<content type="template">source elements read children</content>
<content type="template">source elements read end</content>
<!--source elements value **************************************************-->
<content type="template">source elements value</content>
<!--source elements write file *********************************************-->
<content type="template">source elements write file</content>
<!--source elements write **************************************************-->
<content type="template">source elements write start</content>
<content type="template">source elements write attributes</content>
<content type="template">source elements write mid</content>
<content type="template">source elements write children</content>
<content type="template">source elements write end</content>
</template>
<!--source elements start **********************************************************************-->
<template name="source elements start" type="inline">
<content>
<![CDATA[
//=============================================================================
// Element class <element-vc> implementation
<element-vc>::<element-vc>(const char* f)
{
// Read in document
xmlDocPtr d = xmlParseFile(f);
if (!d)
throw std::runtime_error("file parse failed");
try
{
// Initialize from root node
xmlNodePtr r = xmlDocGetRootElement(d);
if (r)
read(r);
// Clean up
xmlFreeDoc(d);
}
catch (...)
{
xmlFreeDoc(d);
throw;
}
}
<element-vc>::<element-vc>(xmlNodePtr n)
{
// Initialize from node
read(n);
}
]]>
</content>
</template>
<!--source elements operator= start ************************************************************-->
<template name="source elements operator= start" type="inline">
<content>
<![CDATA[
<element-vc>& <element-vc>::operator=(const <element-vc>& r)
{
if (this != &r)
{
]]>
</content>
</template>
<!--source elements operator= attributes *******************************************************-->
<template name="source elements operator= attributes" type="attributes" order="alpha">
<content>
<![CDATA[
_<attribute-Vt> = r._<attribute-Vt>;
]]>
</content>
</template>
<!--source elements operator= children *********************************************************-->
<template name="source elements operator= children" type="children" order="alpha">
<content if="childIsSingle">
<![CDATA[
_<child-vt> = r._<child-vt>;
]]>
</content>
<content if="childIsNotSingle">
<![CDATA[
_<child-vtp> = r._<child-vtp>;
]]>
</content>
</template>
<!--source elements operator= end **************************************************************-->
<template name="source elements operator= end" type="inline">
<content if="hasValue">
<![CDATA[
_values = r._values;
]]>
</content>
<content>
<![CDATA[
}
return *this;
}
]]>
</content>
</template>
<!--source elements read start *****************************************************************-->
<template name="source elements read start" type="inline">
<content>
<![CDATA[
void <element-vc>::read(xmlNodePtr n)
{
// Make sure node is this element
if (xmlStrcmp(n->name, reinterpret_cast<const xmlChar*>("<element>")) != 0)
throw std::runtime_error("expecting node '<element>'");
]]>
</content>
</template>
<!--source elements read attributes ************************************************************-->
<template name="source elements read attributes" type="attributes" order="alpha">
<content if="firstAttribute">
<![CDATA[
// Get attributes if provided
xmlChar* ]]>
</content>
<content if="notFirstAttribute">
<![CDATA[
]]>
</content>
<content>
<![CDATA[
a = xmlGetProp(n, reinterpret_cast<xmlChar*>("<attribute>"));
if (a)
{
_<attribute-Vt> = reinterpret_cast<const char*>(a);
xmlFree(a);
}
]]>
</content>
<content if="lastAttribute">
<![CDATA[
]]>
</content>
</template>
<!--source elements read children **************************************************************-->
<template name="source elements read children" type="children" order="alpha">
<content if="firstChild">
<![CDATA[
// Read the child elements
for (xmlNodePtr s = n->children; s; s = s->next)
{
// Ignore non-element children
if (s->type != XML_ELEMENT_NODE)
continue;
]]>
</content>
<content if="childIsSingle">
<![CDATA[
if (xmlStrcmp(s->name, reinterpret_cast<const xmlChar*>("<child>")) == 0)
{
_<child-vt> = <child-vc>(s);
continue;
}
]]>
</content>
<content if="childIsNotSingle">
<![CDATA[
if (xmlStrcmp(s->name, reinterpret_cast<const xmlChar*>("<child>")) == 0)
{
_<child-vtp>.push_back(<child-vc>(s));
continue;
}
]]>
</content>
<content if="lastChild">
<![CDATA[
}
]]>
</content>
</template>
<!--source elements read end *******************************************************************-->
<template name="source elements read end" type="inline">
<content if="hasValue">
<![CDATA[
// Retreive value
for (xmlNodePtr c = n->children; c; c = c->next)
{
switch (c->type)
{
case XML_TEXT_NODE:
{
xmlChar* t = trim(c->content);
if (*t)
{
_values.push_back(std::make_pair(false,
reinterpret_cast<const char*>(t)));
}
}
break;
case XML_CDATA_SECTION_NODE:
{
xmlChar* t = trim_cdata(c->content);
if (*t)
{
_values.push_back(std::make_pair(false,
reinterpret_cast<const char*>(t)));
}
}
break;
case XML_ELEMENT_NODE:
_values.push_back(std::make_pair(true, std::string()));
break;
}
}
]]>
</content>
<content>
<![CDATA[
}
]]>
</content>
</template>
<!--source elements value **********************************************************************-->
<template name="source elements value" type="inline">
<content if="hasValue">
<![CDATA[
void <element-vc>::value(std::string& v) const
{
const VALUES::const_iterator end = _values.end();
for (VALUES::const_iterator i = _values.begin(); i != end; ++i)
v += i->second;
}
]]>
</content>
</template>
<!--source elements write file *****************************************************************-->
<template name="source elements write file" type="inline">
<content if="writeToFile">
<![CDATA[
void <element-vc>::write(const char* f, bool i, const char* t) const
{
// Create a new writer
xmlTextWriterPtr w = xmlNewTextWriterFilename(f, 0);
if (!w)
throw std::runtime_error("unable to create xmlTextWriter");
// Set indentation if desired
if (i)
{
xmlTextWriterSetIndent(w, 1);
xmlTextWriterSetIndentString(w, reinterpret_cast<xmlChar*>(t ? t : "\t"));
}
try
{
// Create document
int r = xmlTextWriterStartDocument(w, "1.0", "iso8859-1", "yes");
if (r < 0)
throw std::runtime_error("unable to start document");
// Add my content
write(w);
// Close the writer
xmlFreeTextWriter(w);
}
catch (...)
{
xmlFreeTextWriter(w);
throw;
}
}
]]>
</content>
</template>
<!--source elements write start ****************************************************************-->
<template name="source elements write start" type="inline">
<content>
<![CDATA[
void <element-vc>::write(xmlTextWriterPtr w) const
{
// Create element
int r = xmlTextWriterStartElement(w, reinterpret_cast<const xmlChar*>("<element>"));
if (r < 0)
throw std::runtime_error("creation of element '<element>' failed");
]]>
</content>
</template>
<!--source elements write attributes ***********************************************************-->
<template name="source elements write attributes" type="attributes" order="alpha">
<content>
<![CDATA[
// Add attribute <attribute> if needed
if (!_<attribute-Vt>.empty())
{
r = xmlTextWriterWriteAttribute(w, reinterpret_cast<const xmlChar*>("<attribute>"),
reinterpret_cast<const xmlChar*>(_<attribute-Vt>.c_str()));
if (r < 0)
{
throw std::runtime_error("addition of attribute '<attribute>' "
"to element '<element>' failed");
}
}
]]>
</content>
</template>
<!--source elements write mid ******************************************************************-->
<template name="source elements write mid" type="inline">
<content if="hasValue">
<![CDATA[
// Write value if needed
std::string v;
value(v);
if (!v.empty())
{
r = xmlTextWriterWriteString(w, reinterpret_cast<const xmlChar*>(v.c_str()));
if (r < 0)
throw std::runtime_error("failed writing '<element>' value");
}
]]>
</content>
</template>
<!--source elements write children *************************************************************-->
<template name="source elements write children" type="children">
<content if="firstChild">
<![CDATA[
// Add child elements
]]>
</content>
<content if="childIsSingle">
<![CDATA[
_<child-vt>.write(w);
]]>
</content>
<content if="childIsNotSingle">
<![CDATA[
std::for_each(_<child-vtp>.begin(), _<child-vtp>.end(), writer<<child-vc>>(w));
]]>
</content>
<content if="lastChild">
<![CDATA[
]]>
</content>
</template>
<!--source elements write end ******************************************************************-->
<template name="source elements write end" type="inline">
<content>
<![CDATA[
// All done!
r = xmlTextWriterEndElement(w);
if (r < 0)
throw std::runtime_error("failed closing '<element>' element");
}
]]>
</content>
</template>
<!--
****************************************************************************************************************
* REPLACEMENTS *
****************************************************************************************************************
-->
<!--c++ keywords *******************************************************************************-->
<replacement context="global" string="auto">Auto</replacement>
<replacement context="global" string="bool">Bool</replacement>
<replacement context="global" string="break">Break</replacement>
<replacement context="global" string="case">Case</replacement>
<replacement context="global" string="catch">Catch</replacement>
<replacement context="global" string="char">Char</replacement>
<replacement context="global" string="class">Class</replacement>
<replacement context="global" string="const">Const</replacement>
<replacement context="global" string="const_cast">Const_cast</replacement>
<replacement context="global" string="continue">Continue</replacement>
<replacement context="global" string="default">Cefault</replacement>
<replacement context="global" string="delete">Celete</replacement>
<replacement context="global" string="do">Do</replacement>
<replacement context="global" string="double">Double</replacement>
<replacement context="global" string="dynamic_cast">Dynamic_cast</replacement>
<replacement context="global" string="else">Else</replacement>
<replacement context="global" string="enum">Enum</replacement>
<replacement context="global" string="explicit">Explicit</replacement>
<replacement context="global" string="export">Export</replacement>
<replacement context="global" string="extern">Extern</replacement>
<replacement context="global" string="false">False</replacement>
<replacement context="global" string="float">Float</replacement>
<replacement context="global" string="for">For</replacement>
<replacement context="global" string="friend">Friend</replacement>
<replacement context="global" string="goto">Goto</replacement>
<replacement context="global" string="if">If</replacement>
<replacement context="global" string="inline">Inline</replacement>
<replacement context="global" string="int">Int</replacement>
<replacement context="global" string="long">Long</replacement>
<replacement context="global" string="mutable">Mutable</replacement>
<replacement context="global" string="namespace">Namespace</replacement>
<replacement context="global" string="new ">New </replacement>
<replacement context="global" string="operator">Operator</replacement>
<replacement context="global" string="private">Private</replacement>
<replacement context="global" string="protected">Protected</replacement>
<replacement context="global" string="public">Public</replacement>
<replacement context="global" string="register">Register</replacement>
<replacement context="global" string="reinterpret_cast">Reinterpret_cast</replacement>
<replacement context="global" string="return">Return</replacement>
<replacement context="global" string="short">Short</replacement>
<replacement context="global" string="signed">Signed</replacement>
<replacement context="global" string="sizeof">Sizeof</replacement>
<replacement context="global" string="static">Static</replacement>
<replacement context="global" string="static_cast">Static_cast</replacement>
<replacement context="global" string="struct">Struct</replacement>
<replacement context="global" string="switch">Switch</replacement>
<replacement context="global" string="template">Template</replacement>
<replacement context="global" string="this">This</replacement>
<replacement context="global" string="throw">Throw</replacement>
<replacement context="global" string="true">True</replacement>
<replacement context="global" string="try">Try</replacement>
<replacement context="global" string="typedef">Typedef</replacement>
<replacement context="global" string="typeid">Typeid</replacement>
<replacement context="global" string="typename">Typename</replacement>
<replacement context="global" string="union">Union</replacement>
<replacement context="global" string="unsigned">Unsigned</replacement>
<replacement context="global" string="using">Using</replacement>
<replacement context="global" string="virtual">Virtual</replacement>
<replacement context="global" string="void">Void</replacement>
<replacement context="global" string="volatile">Volatile</replacement>
<replacement context="global" string="wchar_t">Wchar_t</replacement>
<replacement context="global" string="while">While</replacement>
<replacement context="global" string="value">Value</replacement>
<!--
****************************************************************************************************************
* CONDITIONALS *
****************************************************************************************************************
-->
<!--
Used to leave out the code for an element's value. Used to prevent to
prevent inclusion of the code, as not all elements make use of their value
(i.e. only only contain children, or their inclusion has meaning itself)
meta: value
type: boolean
-->
<condition name="hasValue" op="and">
<eval op="hasMeta">value</eval>
<eval op="equal" type="boolean">
<left type="meta">value</left>
<right>true</right>
</eval>
</condition>
<!--
Used to determine whether a child element should use a collection, or just
a reference to the child element.
-->
<condition name="isSingle" op="and">
<eval op="hasMeta">single</eval>
<eval op="equal" type="boolean">
<left type="meta">single</left>
<right>true</right>
</eval>
</condition>
<condition name="isNotSingle">
<eval op="not">
<eval op="isSingle" />
</eval>
</condition>
<!-- As above, but for children -->
<condition name="childIsSingle" op="and">
<eval op="childHasMeta">single</eval>
<eval op="equal" type="boolean">
<left type="childMeta">single</left>
<right>true</right>
</eval>
</condition>
<condition name="childIsNotSingle">
<eval op="not">
<eval op="childIsSingle" />
</eval>
</condition>
<!--
Used to prevent member functions for writing to file. Typically, only the
root element needs it, but there are times when a section of sub elements
may need to be written to a file as well, which is why is optional.
-->
<condition name="writeToFile" op="and">
<eval op="hasMeta">writeFile</eval>
<eval op="equal" type="boolean">
<left>true</left>
<right type="meta">writeFile</right> <!-- NOTE: Keep this reversed or right won't get the type attribute -->
</eval>
</condition>
<!--
****************************************************************************************************************
* PLURALS *
* For XCG builds, we have to have one or the code to read them won't be generated *
****************************************************************************************************************
-->
<plural context="" string=""></plural>
<!--
****************************************************************************************************************
* INVALIDS *
* For XCG builds, we have to have one or the code to read them won't be generated *
****************************************************************************************************************
-->
<invalid context="" string=""></invalid>
</generator>