/***************************************************************************
* GXmlAttribute.cpp - XML attribute class implementation *
* ----------------------------------------------------------------------- *
* copyright (C) 2010-2014 by Juergen Knoedlseder *
* ----------------------------------------------------------------------- *
* *
* This program 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. *
* *
* This program 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 this program. If not, see . *
* *
***************************************************************************/
/**
* @file GXmlAttribute.cpp
* @brief XML attribute class implementation
* @author Juergen Knoedlseder
*/
/* __ Includes ___________________________________________________________ */
#ifdef HAVE_CONFIG_H
#include
#endif
#include "GException.hpp"
#include "GTools.hpp"
#include "GXmlAttribute.hpp"
/* __ Method name definitions ____________________________________________ */
#define G_VALUE "GXmlAttribute::value(std::string)"
/* __ Macros _____________________________________________________________ */
/* __ Coding definitions _________________________________________________ */
/* __ Debug definitions __________________________________________________ */
/*==========================================================================
= =
= Constructors/destructors =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Void constructor
***************************************************************************/
GXmlAttribute::GXmlAttribute(void)
{
// Initialise members
init_members();
// Return
return;
}
/***********************************************************************//**
* @brief Copy constructor
*
* @param[in] attr Element attribute.
***************************************************************************/
GXmlAttribute::GXmlAttribute(const GXmlAttribute& attr)
{
// Initialise members
init_members();
// Copy members
copy_members(attr);
// Return
return;
}
/***********************************************************************//**
* @brief Name-Value pair constructor
*
* @param[in] name Attribute name.
* @param[in] value Attribute value.
*
* Construct attribute form a p@ name and a @p value. Predefined entities
* (e.g. ") in attribute values are automatically converted into normal
* characters.
***************************************************************************/
GXmlAttribute::GXmlAttribute(const std::string& name, const std::string& value)
{
// Initialise members
init_members();
// Set attribute
this->name(name);
this->value(gammalib::xml2str(value));
// Return
return;
}
/***********************************************************************//**
* @brief Destructor
***************************************************************************/
GXmlAttribute::~GXmlAttribute(void)
{
// Free members
free_members();
// Return
return;
}
/*==========================================================================
= =
= Operators =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Assignment operator
*
* @param[in] attr Element attribute.
* @return Element attribute.
***************************************************************************/
GXmlAttribute& GXmlAttribute::operator=(const GXmlAttribute& attr)
{
// Execute only if object is not identical
if (this != &attr) {
// Free members
free_members();
// Initialise members
init_members();
// Copy members
copy_members(attr);
} // endif: object was not identical
// Return
return *this;
}
/*==========================================================================
= =
= Public methods =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Clear element attribute
*
* Resets element attribute to a clean initial state.
***************************************************************************/
void GXmlAttribute::clear(void)
{
// Free members
free_members();
// Initialise members
init_members();
// Return
return;
}
/***********************************************************************//**
* @brief Clone element attribute
*
* @return Pointer to deep copy of an element attribute.
***************************************************************************/
GXmlAttribute* GXmlAttribute::clone(void) const
{
// Clone XML attribute
return new GXmlAttribute(*this);
}
/***********************************************************************//**
* @brief Write attribute into URL
*
* @param[in] url Unified Resource Locator.
*
* Writes the element attribute into the @p url. Special characters are
* automatically transformed into predefined entities (e.g. ").
***************************************************************************/
void GXmlAttribute::write(GUrl& url) const
{
// Get value without quotation marks
std::string value = m_value.substr(1, m_value.length()-2);
// Convert value to XML format
value = "\""+gammalib::str2xml(value)+"\"";
// Write attribute into URL
url.printf(" %s=%s", m_name.c_str(), value.c_str());
// Return
return;
}
/***********************************************************************//**
* @brief Print element attribute
*
* @param[in] chatter Chattiness (defaults to NORMAL).
* @return String containing element attribute.
***************************************************************************/
std::string GXmlAttribute::print(const GChatter& chatter) const
{
// Initialise result string
std::string result;
// Continue only if chatter is not silent
if (chatter != SILENT) {
// Append attribute to string
result.append(" "+m_name+"="+m_value);
} // endif: chatter was not silent
// Return
return result;
}
/***********************************************************************//**
* @brief Returns attribute value
*
* @return String containing the attribute value without hyphens.
*
* Returns the attribute value by stripping the hyphens.
***************************************************************************/
std::string GXmlAttribute::value(void) const
{
// Initialise attribute value
std::string value = "";
// Extract value by stripping hyphens
int n = m_value.length();
if (n > 2) {
value = m_value.substr(1, n-2);
}
// Return value
return value;
}
/***********************************************************************//**
* @brief Set attribute value
*
* @param[in] value Attribute value.
*
* @exception GException::xml_attribute_value
* Invalid XML attribute value.
*
* Sets the value of the attribute. The method automatically adds the proper
* hyphens to the value string if they do not exist.
***************************************************************************/
void GXmlAttribute::value(std::string value)
{
// Get length of value string
int n = value.length();
// Count hyphens and signal their presence at start/end
int n_hyphens1 = 0;
int n_hyphens2 = 0;
bool has_hyphens1 = (n >= 2 && value[0] == '\'' && value[n-1] == '\'');
bool has_hyphens2 = (n >= 2 && value[0] == '"' && value[n-1] == '"');
for (int i = 0; i < n; ++i) {
if (value[i] == '\'') n_hyphens1++;
if (value[i] == '"') n_hyphens2++;
}
// Case A: value has ' start and end hyphens. Keep value as is if no other
// ' hyphens are found. Otherwise, if more than 2 ' but no " hyphen is found
// then enclose the value in " hyphens. Finally, if more than 2 ' and at
// least one " hyphen is found we have an invalid value and throw an
// exception.
if (has_hyphens1) {
if (n_hyphens1 > 2 && n_hyphens2 == 0) {
value = "\"" + value + "\"";
}
else if (n_hyphens1 > 2 && n_hyphens2 > 0) {
throw GException::xml_attribute_value(G_VALUE, value);
}
}
// Case B: value has " start and end hyphens. Keep value as is if no other
// " hyphens are found. Otherwise, if more than 2 " but no ' hyphen is found
// then enclose the value in ' hyphens. Finally, if more than 2 " and at
// least one ' hyphen is found we have an invalid value and throw an
// exception.
else if (has_hyphens2) {
if (n_hyphens1 == 0 && n_hyphens2 > 2) {
value = "'" + value + "'";
}
else if (n_hyphens1 > 0 && n_hyphens2 > 2) {
throw GException::xml_attribute_value(G_VALUE, value);
}
}
// Case C: value has no start and end hyphens.
else {
if (n_hyphens1 >= 0 && n_hyphens2 == 0) {
value = "\"" + value + "\"";
}
else if (n_hyphens1 == 0 && n_hyphens2 > 0) {
value = "'" + value + "'";
}
else {
throw GException::xml_attribute_value(G_VALUE, value);
}
}
// Set value
m_value = value;
// Return
return;
}
/*==========================================================================
= =
= Private methods =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Initialise class members
***************************************************************************/
void GXmlAttribute::init_members(void)
{
// Initialise members
m_name.clear();
m_value.clear();
// Return
return;
}
/***********************************************************************//**
* @brief Copy class members
*
* @param[in] attr Element attribute.
***************************************************************************/
void GXmlAttribute::copy_members(const GXmlAttribute& attr)
{
// Copy attributes
m_name = attr.m_name;
m_value = attr.m_value;
// Return
return;
}
/***********************************************************************//**
* @brief Delete class members
***************************************************************************/
void GXmlAttribute::free_members(void)
{
// Return
return;
}