changed: remove XML support for ParameterGroup
This commit is contained in:
@@ -107,12 +107,6 @@ list (APPEND MAIN_SOURCE_FILES
|
|||||||
opm/core/utility/parameters/Parameter.cpp
|
opm/core/utility/parameters/Parameter.cpp
|
||||||
opm/core/utility/parameters/ParameterGroup.cpp
|
opm/core/utility/parameters/ParameterGroup.cpp
|
||||||
opm/core/utility/parameters/ParameterTools.cpp
|
opm/core/utility/parameters/ParameterTools.cpp
|
||||||
opm/core/utility/parameters/ParameterXML.cpp
|
|
||||||
opm/core/utility/parameters/tinyxml/tinystr.cpp
|
|
||||||
opm/core/utility/parameters/tinyxml/tinyxml.cpp
|
|
||||||
opm/core/utility/parameters/tinyxml/tinyxmlerror.cpp
|
|
||||||
opm/core/utility/parameters/tinyxml/tinyxmlparser.cpp
|
|
||||||
opm/core/utility/parameters/tinyxml/xmltest.cpp
|
|
||||||
opm/core/wells/InjectionSpecification.cpp
|
opm/core/wells/InjectionSpecification.cpp
|
||||||
opm/core/wells/ProductionSpecification.cpp
|
opm/core/wells/ProductionSpecification.cpp
|
||||||
opm/core/wells/WellCollection.cpp
|
opm/core/wells/WellCollection.cpp
|
||||||
@@ -157,10 +151,9 @@ list (APPEND TEST_SOURCE_FILES
|
|||||||
)
|
)
|
||||||
|
|
||||||
# originally generated with the command:
|
# originally generated with the command:
|
||||||
# find tests -name '*.xml' -a ! -wholename '*/not-unit/*' -printf '\t%p\n' | sort
|
# find tests -name '*.param' -a ! -wholename '*/not-unit/*' -printf '\t%p\n' | sort
|
||||||
list (APPEND TEST_DATA_FILES
|
list (APPEND TEST_DATA_FILES
|
||||||
tests/extratestdata.xml
|
tests/testdata.param
|
||||||
tests/testdata.xml
|
|
||||||
tests/liveoil.DATA
|
tests/liveoil.DATA
|
||||||
tests/capillary.DATA
|
tests/capillary.DATA
|
||||||
tests/capillary_overlap.DATA
|
tests/capillary_overlap.DATA
|
||||||
@@ -350,9 +343,6 @@ list (APPEND PUBLIC_HEADER_FILES
|
|||||||
opm/core/utility/parameters/ParameterRequirement.hpp
|
opm/core/utility/parameters/ParameterRequirement.hpp
|
||||||
opm/core/utility/parameters/ParameterStrings.hpp
|
opm/core/utility/parameters/ParameterStrings.hpp
|
||||||
opm/core/utility/parameters/ParameterTools.hpp
|
opm/core/utility/parameters/ParameterTools.hpp
|
||||||
opm/core/utility/parameters/ParameterXML.hpp
|
|
||||||
opm/core/utility/parameters/tinyxml/tinystr.h
|
|
||||||
opm/core/utility/parameters/tinyxml/tinyxml.h
|
|
||||||
opm/core/utility/share_obj.hpp
|
opm/core/utility/share_obj.hpp
|
||||||
opm/core/well_controls.h
|
opm/core/well_controls.h
|
||||||
opm/core/wells.h
|
opm/core/wells.h
|
||||||
|
|||||||
@@ -47,7 +47,6 @@
|
|||||||
#include <opm/core/utility/parameters/Parameter.hpp>
|
#include <opm/core/utility/parameters/Parameter.hpp>
|
||||||
#include <opm/core/utility/parameters/ParameterStrings.hpp>
|
#include <opm/core/utility/parameters/ParameterStrings.hpp>
|
||||||
#include <opm/core/utility/parameters/ParameterTools.hpp>
|
#include <opm/core/utility/parameters/ParameterTools.hpp>
|
||||||
#include <opm/core/utility/parameters/ParameterXML.hpp>
|
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
namespace parameter {
|
namespace parameter {
|
||||||
@@ -99,11 +98,6 @@ namespace Opm {
|
|||||||
return get<ParameterGroup>(name);
|
return get<ParameterGroup>(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParameterGroup::readXML(const std::string& xml_filename)
|
|
||||||
{
|
|
||||||
fill_xml(*this, xml_filename, output_is_enabled_);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
inline std::istream&
|
inline std::istream&
|
||||||
samcode_readline(std::istream& is, std::string& parameter) {
|
samcode_readline(std::istream& is, std::string& parameter) {
|
||||||
|
|||||||
@@ -52,8 +52,7 @@ namespace Opm {
|
|||||||
/// given by main). This parses the command line, where each token
|
/// given by main). This parses the command line, where each token
|
||||||
/// either
|
/// either
|
||||||
/// A) specifies a parameter (by a "param=value" token).
|
/// A) specifies a parameter (by a "param=value" token).
|
||||||
/// B) specifies a xml file to be read (by a "filename.xml" token).
|
/// B) specifies a param file to be read (by a "filename.param" token).
|
||||||
/// C) specifies a param file to be read (by a "filename.param" token).
|
|
||||||
/// After the tokens are parsed they are stored in a tree structure
|
/// After the tokens are parsed they are stored in a tree structure
|
||||||
/// in the ParameterGroup object; it is worth mentioning that parameters
|
/// in the ParameterGroup object; it is worth mentioning that parameters
|
||||||
/// are inherited in this tree structure. Thus, if ``grid\_prefix'' is
|
/// are inherited in this tree structure. Thus, if ``grid\_prefix'' is
|
||||||
@@ -76,36 +75,10 @@ namespace Opm {
|
|||||||
/// simulator param=value1 param=value2
|
/// simulator param=value1 param=value2
|
||||||
/// will use value2 as the value of ``param''.
|
/// will use value2 as the value of ``param''.
|
||||||
///
|
///
|
||||||
/// XML parameters
|
|
||||||
///
|
|
||||||
/// In the introduction to this section it was mentioned that the parameters for
|
|
||||||
/// the simulator are organized in a tree structure. This is mirrored in the XML
|
|
||||||
/// file by the use of groups; a group is a collection of parameters and subgroups
|
|
||||||
/// enclosed by a \fixed{<ParameterGroup>}-\fixed{</ParameterGroup>} pair. The only
|
|
||||||
/// attribute of relevance in a \fixed{ParameterGroup} tag is that of \fixed{name},
|
|
||||||
/// which is used to navigate in the tree.
|
|
||||||
/// The actual parameters are specified by the \fixed{<Parameter />} tag. Each
|
|
||||||
/// parameter has three attributes: \fixed{name}, \fixed{type}, and \fixed{value}.
|
|
||||||
/// Both name and value should be evident. Type is one of \fixed{bool} (for things
|
|
||||||
/// that are either true or false), \fixed{int} (for integers), \fixed{double} (for
|
|
||||||
/// floating point numbers with double precision), \fixed{string} (for text
|
|
||||||
/// strings), or \fixed{file} (for files and directories relative to the location
|
|
||||||
/// of the XML file).
|
|
||||||
///
|
|
||||||
/// param files
|
/// param files
|
||||||
///
|
///
|
||||||
/// A param file consists of multiple lienes, where each line consists of "param=value".
|
/// A param file consists of multiple lienes, where each line consists of "param=value".
|
||||||
/// This syntax is identical to the one for paramters specified on the command line.
|
/// This syntax is identical to the one for parameters specified on the command line.
|
||||||
///
|
|
||||||
///
|
|
||||||
/// If one combines both XML files and parameters, one should note that that if a parameter
|
|
||||||
/// is specified on the command line is also found in a XML file, the parameter
|
|
||||||
/// specified on the command line is the one used. Thus, if ``parameters.xml''
|
|
||||||
/// specifies that ``stepsize'' is 2.71828 while, the command used to run the
|
|
||||||
/// application ``simulator'' is
|
|
||||||
/// simulator stepsize=3.14159 parameters.xml
|
|
||||||
/// the simulator will run with ``stepsize'' equal to 3.14159.
|
|
||||||
///
|
|
||||||
class ParameterGroup : public ParameterMapItem {
|
class ParameterGroup : public ParameterMapItem {
|
||||||
public:
|
public:
|
||||||
struct NotFoundException : public std::exception {};
|
struct NotFoundException : public std::exception {};
|
||||||
@@ -128,7 +101,7 @@ namespace Opm {
|
|||||||
///
|
///
|
||||||
/// It is required that argv[0] is the program name, while if
|
/// It is required that argv[0] is the program name, while if
|
||||||
/// 0 < i < argc, then argv[i] is either
|
/// 0 < i < argc, then argv[i] is either
|
||||||
/// the name of an xml file, parameter file or parametername=value.
|
/// the name of a parameter file or parametername=value.
|
||||||
///
|
///
|
||||||
/// \param argc is the number of command-line arguments,
|
/// \param argc is the number of command-line arguments,
|
||||||
/// including the name of the executable.
|
/// including the name of the executable.
|
||||||
@@ -212,13 +185,6 @@ namespace Opm {
|
|||||||
/// getGroup is enabled.
|
/// getGroup is enabled.
|
||||||
bool isOutputEnabled() const;
|
bool isOutputEnabled() const;
|
||||||
|
|
||||||
|
|
||||||
/// \brief Reads the contents of the xml file specified by
|
|
||||||
/// xml_filename into this ParameterGroup.
|
|
||||||
///
|
|
||||||
/// \param xml_filename is the name of a xml file.
|
|
||||||
void readXML(const std::string& xml_filename);
|
|
||||||
|
|
||||||
/// \brief Reads the contents of the param file specified by
|
/// \brief Reads the contents of the param file specified by
|
||||||
/// param_filename into this ParameterGroup.
|
/// param_filename into this ParameterGroup.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ namespace Opm {
|
|||||||
{
|
{
|
||||||
if (verify_syntax && (argc < 2)) {
|
if (verify_syntax && (argc < 2)) {
|
||||||
std::cerr << "Usage: " << argv[0] << " "
|
std::cerr << "Usage: " << argv[0] << " "
|
||||||
<< "[paramfilename1.{xml,param}] "
|
<< "[paramfilename1.param] "
|
||||||
<< "[paramfilename2.{xml,param}] "
|
<< "[paramfilename2.param] "
|
||||||
<< "[overridden_arg1=value1] "
|
<< "[overridden_arg1=value1] "
|
||||||
<< "[overridden_arg2=value2] "
|
<< "[overridden_arg2=value2] "
|
||||||
<< "[...]" << std::endl;
|
<< "[...]" << std::endl;
|
||||||
@@ -150,14 +150,12 @@ namespace Opm {
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < int(files.size()); ++i) {
|
for (int i = 0; i < int(files.size()); ++i) {
|
||||||
std::pair<std::string, std::string> file_type = filename_split(files[i]);
|
std::pair<std::string, std::string> file_type = filename_split(files[i]);
|
||||||
if (file_type.second == "xml") {
|
if (file_type.second == "param") {
|
||||||
this->readXML(files[i]);
|
|
||||||
} else if (file_type.second == "param") {
|
|
||||||
this->readParam(files[i]);
|
this->readParam(files[i]);
|
||||||
} else {
|
} else {
|
||||||
if (verify_syntax) {
|
if (verify_syntax) {
|
||||||
std::cerr << "ERROR: Input '" << files[i] << "' is not a valid name for a parameter file.\n";
|
std::cerr << "ERROR: Input '" << files[i] << "' is not a valid name for a parameter file.\n";
|
||||||
std::cerr << " Valid filename extensions are 'xml' and 'param'.\n";
|
std::cerr << " Valid filename extensions are 'param'.\n";
|
||||||
OPM_THROW(std::runtime_error, "ParameterGroup cannot handle argument: " << files[i]);
|
OPM_THROW(std::runtime_error, "ParameterGroup cannot handle argument: " << files[i]);
|
||||||
} else {
|
} else {
|
||||||
unhandled_arguments_.push_back(files[i]);
|
unhandled_arguments_.push_back(files[i]);
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ namespace Opm {
|
|||||||
|
|
||||||
const std::string ID_xmltag__param_grp = "ParameterGroup";
|
const std::string ID_xmltag__param_grp = "ParameterGroup";
|
||||||
const std::string ID_xmltag__param = "Parameter";
|
const std::string ID_xmltag__param = "Parameter";
|
||||||
const std::string ID_xmltag__file_param_grp = "ParameterGroupFromFile";
|
|
||||||
const std::string ID_xmltag__file_params = "MergeWithFile";
|
|
||||||
|
|
||||||
const std::string ID_xmlatt__value = "value";
|
|
||||||
const std::string ID_xmlatt__name = "name";
|
|
||||||
const std::string ID_xmlatt__type = "type";
|
|
||||||
|
|
||||||
const std::string ID_param_type__bool = "bool";
|
const std::string ID_param_type__bool = "bool";
|
||||||
const std::string ID_param_type__int = "int";
|
const std::string ID_param_type__int = "int";
|
||||||
|
|||||||
@@ -1,141 +0,0 @@
|
|||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// File: ParameterXML.cpp
|
|
||||||
//
|
|
||||||
// Created: Tue Jun 2 18:57:25 2009
|
|
||||||
//
|
|
||||||
// Author(s): B<>rd Skaflestad <bard.skaflestad@sintef.no>
|
|
||||||
// Atgeirr F Rasmussen <atgeirr@sintef.no>
|
|
||||||
//
|
|
||||||
// $Date$
|
|
||||||
//
|
|
||||||
// $Revision$
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
|
|
||||||
Copyright 2009, 2010 Statoil ASA.
|
|
||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
|
||||||
|
|
||||||
OPM is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OPM is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#include <opm/core/utility/parameters/ParameterXML.hpp>
|
|
||||||
#include <opm/core/utility/parameters/Parameter.hpp>
|
|
||||||
#include <opm/core/utility/parameters/ParameterStrings.hpp>
|
|
||||||
|
|
||||||
#include <exception>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
|
|
||||||
#include <opm/core/utility/parameters/tinyxml/tinyxml.h>
|
|
||||||
|
|
||||||
namespace Opm {
|
|
||||||
namespace parameter {
|
|
||||||
|
|
||||||
namespace tinyxml {
|
|
||||||
std::string getProperty(const std::string& property,
|
|
||||||
const TiXmlElement* node_ptr);
|
|
||||||
void read_xml(ParameterGroup& pg, const std::string filename,
|
|
||||||
const bool enable_output);
|
|
||||||
void fill_tree(ParameterGroup& pg,
|
|
||||||
const TiXmlNode* root,
|
|
||||||
const std::string& xml_file_path,
|
|
||||||
const bool enable_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill_xml(ParameterGroup& pg, const std::string filename,
|
|
||||||
const bool enable_output) {
|
|
||||||
tinyxml::read_xml(pg, filename, enable_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace tinyxml {
|
|
||||||
std::string getProperty(const std::string& property,
|
|
||||||
const TiXmlElement* node_ptr)
|
|
||||||
{
|
|
||||||
const char* prop_value_ptr = node_ptr->Attribute(property.c_str());
|
|
||||||
std::string property_value(prop_value_ptr ? prop_value_ptr : "");
|
|
||||||
return property_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_xml(ParameterGroup& pg, const std::string filename, const bool enable_output)
|
|
||||||
{
|
|
||||||
TiXmlDocument doc(filename);
|
|
||||||
bool ok = doc.LoadFile();
|
|
||||||
if (!ok) {
|
|
||||||
std::cerr << "ERROR: Failed to open XML file '" << filename << "'\n";
|
|
||||||
throw std::exception();
|
|
||||||
}
|
|
||||||
const TiXmlNode* root = doc.RootElement();
|
|
||||||
std::string xml_file_path = boost::filesystem::path(filename).branch_path().string();
|
|
||||||
fill_tree(pg, root, xml_file_path, enable_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill_tree(ParameterGroup& pg,
|
|
||||||
const TiXmlNode* root,
|
|
||||||
const std::string& xml_file_path,
|
|
||||||
const bool enable_output)
|
|
||||||
{
|
|
||||||
//std::cout << "GROUP '" << value << "' BEGIN\n";
|
|
||||||
for (const TiXmlNode* cur = root->FirstChild(); cur; cur = cur->NextSibling()) {
|
|
||||||
const TiXmlElement* elem = cur->ToElement();
|
|
||||||
if (elem) {
|
|
||||||
std::string tag_name = elem->ValueStr();
|
|
||||||
if (tag_name == ID_xmltag__file_params) {
|
|
||||||
std::string relative_filename = getProperty(ID_xmlatt__value, elem);
|
|
||||||
std::string filename = (boost::filesystem::path(xml_file_path) / relative_filename).string();
|
|
||||||
fill_xml(pg, filename, enable_output);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::string name = getProperty(ID_xmlatt__name, elem);
|
|
||||||
std::shared_ptr<ParameterMapItem> data;
|
|
||||||
if (tag_name == ID_xmltag__param) {
|
|
||||||
std::string value = getProperty(ID_xmlatt__value, elem);
|
|
||||||
std::string type = getProperty(ID_xmlatt__type, elem);
|
|
||||||
if (type == ID_param_type__file) {
|
|
||||||
value = (boost::filesystem::path(xml_file_path) / value).string();
|
|
||||||
type = ID_param_type__string;
|
|
||||||
}
|
|
||||||
data.reset(new Parameter(value, type));
|
|
||||||
} else if (tag_name == ID_xmltag__param_grp) {
|
|
||||||
std::string child_path = pg.path() + ID_delimiter_path + name;
|
|
||||||
data.reset(new ParameterGroup(child_path, &pg, enable_output));
|
|
||||||
fill_tree(dynamic_cast<ParameterGroup&>(*data), elem, xml_file_path,
|
|
||||||
enable_output);
|
|
||||||
} else if (tag_name == ID_xmltag__file_param_grp) {
|
|
||||||
std::string child_path = pg.path() + ID_delimiter_path + name;
|
|
||||||
data.reset(new ParameterGroup(child_path, &pg, enable_output));
|
|
||||||
std::string relative_filename = getProperty(ID_xmlatt__value, elem);
|
|
||||||
std::string filename = (boost::filesystem::path(xml_file_path) / relative_filename).string();
|
|
||||||
fill_xml(dynamic_cast<ParameterGroup&>(*data), filename, enable_output);
|
|
||||||
} else {
|
|
||||||
std::cerr << "ERROR: '" << tag_name << "' is an unknown xml tag.\n";
|
|
||||||
throw std::exception();
|
|
||||||
}
|
|
||||||
pg.insert(name, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//std::cout << "GROUP '" << id << "' END\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace parameter
|
|
||||||
} // namespace Opm
|
|
||||||
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// File: ParameterXML.hpp
|
|
||||||
//
|
|
||||||
// Created: Tue Jun 2 18:55:59 2009
|
|
||||||
//
|
|
||||||
// Author(s): B<>rd Skaflestad <bard.skaflestad@sintef.no>
|
|
||||||
// Atgeirr F Rasmussen <atgeirr@sintef.no>
|
|
||||||
//
|
|
||||||
// $Date$
|
|
||||||
//
|
|
||||||
// $Revision$
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
|
|
||||||
Copyright 2009, 2010 Statoil ASA.
|
|
||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
|
||||||
|
|
||||||
OPM is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OPM is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OPM_PARAMETERXML_HEADER
|
|
||||||
#define OPM_PARAMETERXML_HEADER
|
|
||||||
|
|
||||||
#include <opm/core/utility/parameters/ParameterGroup.hpp>
|
|
||||||
|
|
||||||
namespace Opm {
|
|
||||||
namespace parameter {
|
|
||||||
/// \brief This function fills a ParameterGroup with a XML file.
|
|
||||||
///
|
|
||||||
/// NOTE: The function throws if there is an error during reading
|
|
||||||
/// of the XML file.
|
|
||||||
///
|
|
||||||
/// \retval pg is the ParameterGroup to be filled.
|
|
||||||
/// \param filename is the name of an XML file.
|
|
||||||
void fill_xml(ParameterGroup& pg, const std::string filename, const bool enable_output);
|
|
||||||
} // namespace parameter
|
|
||||||
} // namespace Opm
|
|
||||||
|
|
||||||
#endif // OPM_PARAMETERXML_HEADER
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<!-- parameter groups contains nested groups, values, or
|
|
||||||
inclusion from files (either at this level, or as a sub-group) -->
|
|
||||||
<!ELEMENT ParameterGroup (ParameterGroup |
|
|
||||||
Parameter |
|
|
||||||
ParameterGroupFromFile |
|
|
||||||
MergeWithFile)*>
|
|
||||||
<!-- note: top-level group has implied name, sub-groups must be specified -->
|
|
||||||
<!ATTLIST ParameterGroup name NMTOKEN #IMPLIED>
|
|
||||||
|
|
||||||
<!-- single value parameters. filenames can have either relative or absolute paths -->
|
|
||||||
<!ELEMENT Parameter EMPTY>
|
|
||||||
<!ATTLIST Parameter type (bool | int | double | string | file | cmdline) #REQUIRED
|
|
||||||
name NMTOKEN #REQUIRED
|
|
||||||
value CDATA #REQUIRED
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- include parameters from another file, as a named sub-group
|
|
||||||
(the nameless top-level in that file becomes "name" in this) -->
|
|
||||||
<!ELEMENT ParameterGroupFromFile EMPTY>
|
|
||||||
<!ATTLIST ParameterGroupFromFile name NMTOKEN #REQUIRED
|
|
||||||
value CDATA #REQUIRED
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- include parameters from another file as if they were given on this level -->
|
|
||||||
<!ELEMENT MergeWithFile EMPTY>
|
|
||||||
<!ATTLIST MergeWithFile value CDATA #REQUIRED>
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
www.sourceforge.net/projects/tinyxml
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any
|
|
||||||
damages arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any
|
|
||||||
purpose, including commercial applications, and to alter it and
|
|
||||||
redistribute it freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must
|
|
||||||
not claim that you wrote the original software. If you use this
|
|
||||||
software in a product, an acknowledgment in the product documentation
|
|
||||||
would be appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and
|
|
||||||
must not be misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef TIXML_USE_STL
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "tinystr.h"
|
|
||||||
|
|
||||||
// Error value for find primitive
|
|
||||||
const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
|
|
||||||
|
|
||||||
|
|
||||||
// Null rep.
|
|
||||||
TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
|
|
||||||
|
|
||||||
|
|
||||||
void TiXmlString::reserve (size_type cap)
|
|
||||||
{
|
|
||||||
if (cap > capacity())
|
|
||||||
{
|
|
||||||
TiXmlString tmp;
|
|
||||||
tmp.init(length(), cap);
|
|
||||||
memcpy(tmp.start(), data(), length());
|
|
||||||
swap(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TiXmlString& TiXmlString::assign(const char* str, size_type len)
|
|
||||||
{
|
|
||||||
size_type cap = capacity();
|
|
||||||
if (len > cap || cap > 3*(len + 8))
|
|
||||||
{
|
|
||||||
TiXmlString tmp;
|
|
||||||
tmp.init(len);
|
|
||||||
memcpy(tmp.start(), str, len);
|
|
||||||
swap(tmp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memmove(start(), str, len);
|
|
||||||
set_size(len);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TiXmlString& TiXmlString::append(const char* str, size_type len)
|
|
||||||
{
|
|
||||||
size_type newsize = length() + len;
|
|
||||||
if (newsize > capacity())
|
|
||||||
{
|
|
||||||
reserve (newsize + capacity());
|
|
||||||
}
|
|
||||||
memmove(finish(), str, len);
|
|
||||||
set_size(newsize);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
|
|
||||||
{
|
|
||||||
TiXmlString tmp;
|
|
||||||
tmp.reserve(a.length() + b.length());
|
|
||||||
tmp += a;
|
|
||||||
tmp += b;
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
TiXmlString operator + (const TiXmlString & a, const char* b)
|
|
||||||
{
|
|
||||||
TiXmlString tmp;
|
|
||||||
TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
|
|
||||||
tmp.reserve(a.length() + b_len);
|
|
||||||
tmp += a;
|
|
||||||
tmp.append(b, b_len);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
TiXmlString operator + (const char* a, const TiXmlString & b)
|
|
||||||
{
|
|
||||||
TiXmlString tmp;
|
|
||||||
TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
|
|
||||||
tmp.reserve(a_len + b.length());
|
|
||||||
tmp.append(a, a_len);
|
|
||||||
tmp += b;
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // TIXML_USE_STL
|
|
||||||
@@ -1,305 +0,0 @@
|
|||||||
/*
|
|
||||||
www.sourceforge.net/projects/tinyxml
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any
|
|
||||||
damages arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any
|
|
||||||
purpose, including commercial applications, and to alter it and
|
|
||||||
redistribute it freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must
|
|
||||||
not claim that you wrote the original software. If you use this
|
|
||||||
software in a product, an acknowledgment in the product documentation
|
|
||||||
would be appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and
|
|
||||||
must not be misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef TIXML_USE_STL
|
|
||||||
|
|
||||||
#ifndef TIXML_STRING_INCLUDED
|
|
||||||
#define TIXML_STRING_INCLUDED
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* The support for explicit isn't that universal, and it isn't really
|
|
||||||
required - it is used to check that the TiXmlString class isn't incorrectly
|
|
||||||
used. Be nice to old compilers and macro it here:
|
|
||||||
*/
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
|
|
||||||
// Microsoft visual studio, version 6 and higher.
|
|
||||||
#define TIXML_EXPLICIT explicit
|
|
||||||
#elif defined(__GNUC__) && (__GNUC__ >= 3 )
|
|
||||||
// GCC version 3 and higher.s
|
|
||||||
#define TIXML_EXPLICIT explicit
|
|
||||||
#else
|
|
||||||
#define TIXML_EXPLICIT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
TiXmlString is an emulation of a subset of the std::string template.
|
|
||||||
Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
|
|
||||||
Only the member functions relevant to the TinyXML project have been implemented.
|
|
||||||
The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
|
|
||||||
a string and there's no more room, we allocate a buffer twice as big as we need.
|
|
||||||
*/
|
|
||||||
class TiXmlString
|
|
||||||
{
|
|
||||||
public :
|
|
||||||
// The size type used
|
|
||||||
typedef size_t size_type;
|
|
||||||
|
|
||||||
// Error value for find primitive
|
|
||||||
static const size_type npos; // = -1;
|
|
||||||
|
|
||||||
|
|
||||||
// TiXmlString empty constructor
|
|
||||||
TiXmlString () : rep_(&nullrep_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlString copy constructor
|
|
||||||
TiXmlString ( const TiXmlString & copy) : rep_(0)
|
|
||||||
{
|
|
||||||
init(copy.length());
|
|
||||||
memcpy(start(), copy.data(), length());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlString constructor, based on a string
|
|
||||||
TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
|
|
||||||
{
|
|
||||||
init( static_cast<size_type>( strlen(copy) ));
|
|
||||||
memcpy(start(), copy, length());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlString constructor, based on a string
|
|
||||||
TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
|
|
||||||
{
|
|
||||||
init(len);
|
|
||||||
memcpy(start(), str, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlString destructor
|
|
||||||
~TiXmlString ()
|
|
||||||
{
|
|
||||||
quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
TiXmlString& operator = (const char * copy)
|
|
||||||
{
|
|
||||||
return assign( copy, (size_type)strlen(copy));
|
|
||||||
}
|
|
||||||
|
|
||||||
TiXmlString& operator = (const TiXmlString & copy)
|
|
||||||
{
|
|
||||||
return assign(copy.start(), copy.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// += operator. Maps to append
|
|
||||||
TiXmlString& operator += (const char * suffix)
|
|
||||||
{
|
|
||||||
return append(suffix, static_cast<size_type>( strlen(suffix) ));
|
|
||||||
}
|
|
||||||
|
|
||||||
// += operator. Maps to append
|
|
||||||
TiXmlString& operator += (char single)
|
|
||||||
{
|
|
||||||
return append(&single, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// += operator. Maps to append
|
|
||||||
TiXmlString& operator += (const TiXmlString & suffix)
|
|
||||||
{
|
|
||||||
return append(suffix.data(), suffix.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Convert a TiXmlString into a null-terminated char *
|
|
||||||
const char * c_str () const { return rep_->str; }
|
|
||||||
|
|
||||||
// Convert a TiXmlString into a char * (need not be null terminated).
|
|
||||||
const char * data () const { return rep_->str; }
|
|
||||||
|
|
||||||
// Return the length of a TiXmlString
|
|
||||||
size_type length () const { return rep_->size; }
|
|
||||||
|
|
||||||
// Alias for length()
|
|
||||||
size_type size () const { return rep_->size; }
|
|
||||||
|
|
||||||
// Checks if a TiXmlString is empty
|
|
||||||
bool empty () const { return rep_->size == 0; }
|
|
||||||
|
|
||||||
// Return capacity of string
|
|
||||||
size_type capacity () const { return rep_->capacity; }
|
|
||||||
|
|
||||||
|
|
||||||
// single char extraction
|
|
||||||
const char& at (size_type index) const
|
|
||||||
{
|
|
||||||
assert( index < length() );
|
|
||||||
return rep_->str[ index ];
|
|
||||||
}
|
|
||||||
|
|
||||||
// [] operator
|
|
||||||
char& operator [] (size_type index) const
|
|
||||||
{
|
|
||||||
assert( index < length() );
|
|
||||||
return rep_->str[ index ];
|
|
||||||
}
|
|
||||||
|
|
||||||
// find a char in a string. Return TiXmlString::npos if not found
|
|
||||||
size_type find (char lookup) const
|
|
||||||
{
|
|
||||||
return find(lookup, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// find a char in a string from an offset. Return TiXmlString::npos if not found
|
|
||||||
size_type find (char tofind, size_type offset) const
|
|
||||||
{
|
|
||||||
if (offset >= length()) return npos;
|
|
||||||
|
|
||||||
for (const char* p = c_str() + offset; *p != '\0'; ++p)
|
|
||||||
{
|
|
||||||
if (*p == tofind) return static_cast< size_type >( p - c_str() );
|
|
||||||
}
|
|
||||||
return npos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear ()
|
|
||||||
{
|
|
||||||
//Lee:
|
|
||||||
//The original was just too strange, though correct:
|
|
||||||
// TiXmlString().swap(*this);
|
|
||||||
//Instead use the quit & re-init:
|
|
||||||
quit();
|
|
||||||
init(0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Function to reserve a big amount of data when we know we'll need it. Be aware that this
|
|
||||||
function DOES NOT clear the content of the TiXmlString if any exists.
|
|
||||||
*/
|
|
||||||
void reserve (size_type cap);
|
|
||||||
|
|
||||||
TiXmlString& assign (const char* str, size_type len);
|
|
||||||
|
|
||||||
TiXmlString& append (const char* str, size_type len);
|
|
||||||
|
|
||||||
void swap (TiXmlString& other)
|
|
||||||
{
|
|
||||||
Rep* r = rep_;
|
|
||||||
rep_ = other.rep_;
|
|
||||||
other.rep_ = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void init(size_type sz) { init(sz, sz); }
|
|
||||||
void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
|
|
||||||
char* start() const { return rep_->str; }
|
|
||||||
char* finish() const { return rep_->str + rep_->size; }
|
|
||||||
|
|
||||||
struct Rep
|
|
||||||
{
|
|
||||||
size_type size, capacity;
|
|
||||||
char str[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
void init(size_type sz, size_type cap)
|
|
||||||
{
|
|
||||||
if (cap)
|
|
||||||
{
|
|
||||||
// Lee: the original form:
|
|
||||||
// rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
|
|
||||||
// doesn't work in some cases of new being overloaded. Switching
|
|
||||||
// to the normal allocation, although use an 'int' for systems
|
|
||||||
// that are overly picky about structure alignment.
|
|
||||||
const size_type bytesNeeded = sizeof(Rep) + cap;
|
|
||||||
const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
|
|
||||||
rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
|
|
||||||
|
|
||||||
rep_->str[ rep_->size = sz ] = '\0';
|
|
||||||
rep_->capacity = cap;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rep_ = &nullrep_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void quit()
|
|
||||||
{
|
|
||||||
if (rep_ != &nullrep_)
|
|
||||||
{
|
|
||||||
// The rep_ is really an array of ints. (see the allocator, above).
|
|
||||||
// Cast it back before delete, so the compiler won't incorrectly call destructors.
|
|
||||||
delete [] ( reinterpret_cast<int*>( rep_ ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rep * rep_;
|
|
||||||
static Rep nullrep_;
|
|
||||||
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
inline bool operator == (const TiXmlString & a, const TiXmlString & b)
|
|
||||||
{
|
|
||||||
return ( a.length() == b.length() ) // optimization on some platforms
|
|
||||||
&& ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
|
|
||||||
}
|
|
||||||
inline bool operator < (const TiXmlString & a, const TiXmlString & b)
|
|
||||||
{
|
|
||||||
return strcmp(a.c_str(), b.c_str()) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
|
|
||||||
inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
|
|
||||||
inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
|
|
||||||
inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
|
|
||||||
|
|
||||||
inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
|
|
||||||
inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
|
|
||||||
inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
|
|
||||||
inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
|
|
||||||
|
|
||||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
|
|
||||||
TiXmlString operator + (const TiXmlString & a, const char* b);
|
|
||||||
TiXmlString operator + (const char* a, const TiXmlString & b);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
|
|
||||||
Only the operators that we need for TinyXML have been developped.
|
|
||||||
*/
|
|
||||||
class TiXmlOutStream : public TiXmlString
|
|
||||||
{
|
|
||||||
public :
|
|
||||||
|
|
||||||
// TiXmlOutStream << operator.
|
|
||||||
TiXmlOutStream & operator << (const TiXmlString & in)
|
|
||||||
{
|
|
||||||
*this += in;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TiXmlOutStream << operator.
|
|
||||||
TiXmlOutStream & operator << (const char * in)
|
|
||||||
{
|
|
||||||
*this += in;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
} ;
|
|
||||||
|
|
||||||
#endif // TIXML_STRING_INCLUDED
|
|
||||||
#endif // TIXML_USE_STL
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
www.sourceforge.net/projects/tinyxml
|
|
||||||
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any
|
|
||||||
damages arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any
|
|
||||||
purpose, including commercial applications, and to alter it and
|
|
||||||
redistribute it freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must
|
|
||||||
not claim that you wrote the original software. If you use this
|
|
||||||
software in a product, an acknowledgment in the product documentation
|
|
||||||
would be appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and
|
|
||||||
must not be misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "tinyxml.h"
|
|
||||||
|
|
||||||
// The goal of the seperate error file is to make the first
|
|
||||||
// step towards localization. tinyxml (currently) only supports
|
|
||||||
// english error messages, but the could now be translated.
|
|
||||||
//
|
|
||||||
// It also cleans up the code a bit.
|
|
||||||
//
|
|
||||||
|
|
||||||
const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] =
|
|
||||||
{
|
|
||||||
"No error",
|
|
||||||
"Error",
|
|
||||||
"Failed to open file",
|
|
||||||
"Error parsing Element.",
|
|
||||||
"Failed to read Element name",
|
|
||||||
"Error reading Element value.",
|
|
||||||
"Error reading Attributes.",
|
|
||||||
"Error: empty tag.",
|
|
||||||
"Error reading end tag.",
|
|
||||||
"Error parsing Unknown.",
|
|
||||||
"Error parsing Comment.",
|
|
||||||
"Error parsing Declaration.",
|
|
||||||
"Error document empty.",
|
|
||||||
"Error null (0) or unexpected EOF found in input stream.",
|
|
||||||
"Error parsing CDATA.",
|
|
||||||
"Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
|
|
||||||
};
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,8 +0,0 @@
|
|||||||
<?xml version = '1.0' encoding = 'ISO-8859-1'?>
|
|
||||||
<ParameterGroup>
|
|
||||||
<ParameterGroup name="group">
|
|
||||||
<ParameterGroup name="subgroup">
|
|
||||||
<Parameter type="int" name="anotheritem" value="4"/>
|
|
||||||
</ParameterGroup>
|
|
||||||
</ParameterGroup>
|
|
||||||
</ParameterGroup>
|
|
||||||
@@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(xml_syntax_init)
|
|||||||
{
|
{
|
||||||
typedef const char* cp;
|
typedef const char* cp;
|
||||||
std::vector<cp> argv = { "program_command",
|
std::vector<cp> argv = { "program_command",
|
||||||
"testdata.xml",
|
"testdata.param",
|
||||||
"/group/item=overridingstring",
|
"/group/item=overridingstring",
|
||||||
"unhandledargument",
|
"unhandledargument",
|
||||||
0};
|
0};
|
||||||
@@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE(failing_strict_xml_syntax_init)
|
|||||||
{
|
{
|
||||||
typedef const char* cp;
|
typedef const char* cp;
|
||||||
std::vector<cp> argv = { "program_command",
|
std::vector<cp> argv = { "program_command",
|
||||||
"testdata.xml",
|
"testdata.param",
|
||||||
"/group/item=overridingstring",
|
"/group/item=overridingstring",
|
||||||
"unhandledargument",
|
"unhandledargument",
|
||||||
0 };
|
0 };
|
||||||
|
|||||||
6
tests/testdata.param
Normal file
6
tests/testdata.param
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
topitem=somestring
|
||||||
|
/slashtopitem=anotherstring
|
||||||
|
/group/item=1
|
||||||
|
/group/anotheritem=2
|
||||||
|
/group/subgroup/item=3
|
||||||
|
/group/subgroup/anotheritem=4
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<?xml version = '1.0' encoding = 'ISO-8859-1'?>
|
|
||||||
<ParameterGroup>
|
|
||||||
<MergeWithFile value="extratestdata.xml"/>
|
|
||||||
<Parameter type="string" name="topitem" value="somestring"/>
|
|
||||||
<Parameter type="string" name="slashtopitem" value="anotherstring"/>
|
|
||||||
<ParameterGroup name="group">
|
|
||||||
<Parameter type="int" name="item" value="1"/>
|
|
||||||
<Parameter type="int" name="anotheritem" value="2"/>
|
|
||||||
<ParameterGroup name="subgroup">
|
|
||||||
<Parameter type="int" name="item" value="3"/>
|
|
||||||
</ParameterGroup>
|
|
||||||
</ParameterGroup>
|
|
||||||
</ParameterGroup>
|
|
||||||
Reference in New Issue
Block a user