Files correlati : Ricompilazione Demo : [ ] Commento : Corretta lettura file xml git-svn-id: svn://10.65.10.50/trunk@11948 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			559 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			559 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include "real.h"
 | 
						|
#include "xml.h"
 | 
						|
 | 
						|
#ifdef WIN32
 | 
						|
#include <fstream.h>
 | 
						|
#include <strstrea.h>
 | 
						|
#else
 | 
						|
#include <incstr.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Utilities
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
void Spaces(ostream& outf, int nSpaces)
 | 
						|
{
 | 
						|
	outf << '\n';
 | 
						|
	if (nSpaces > 0)
 | 
						|
	{
 | 
						|
		TString str(nSpaces, ' '); 
 | 
						|
		str.print_on(outf);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
int hex2int(const char* str)
 | 
						|
{
 | 
						|
	int n = 0;
 | 
						|
	for (int i = 0; str[i]; i++)
 | 
						|
	{
 | 
						|
		if (str[i] >= '0' && str[i] <= '9')
 | 
						|
		{
 | 
						|
  		n *= 16;
 | 
						|
      n += str[i]-'0';
 | 
						|
		} else
 | 
						|
		if (str[i] >= 'A' && str[i] <= 'F')
 | 
						|
		{
 | 
						|
  		n *= 16;
 | 
						|
		  n += str[i]-'A'+10;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	return n;
 | 
						|
}
 | 
						|
 | 
						|
const TString& EscapeSequence(char cStart, istream& inf)
 | 
						|
{
 | 
						|
	TString& str = get_tmp_string();
 | 
						|
 | 
						|
	if (cStart == '&')
 | 
						|
	{
 | 
						|
		for (char c = inf.get(); c != ';'; c = inf.get())
 | 
						|
			str << c;
 | 
						|
    if (str[0] == '#')
 | 
						|
    {
 | 
						|
		  str[0] = hex2int((const char*)str+1);
 | 
						|
      str[1] = '\0';
 | 
						|
    } else
 | 
						|
    if (str[0] >= '0' && str[0] <= '9')
 | 
						|
    {
 | 
						|
		  str[0] = atoi(str);
 | 
						|
      str[1] = '\0';
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
		  if (str == "lt") return str ="<";
 | 
						|
		  if (str == "gt") return str =">";
 | 
						|
		  if (str == "nbsp") return str =" ";
 | 
						|
		  if (str == "Agrave") return str ="À";
 | 
						|
		  if (str == "Egrave") return str ="È";
 | 
						|
		  if (str == "Eacuto") return str ="É";
 | 
						|
		  if (str == "Igrave") return str ="Ì";
 | 
						|
		  if (str == "Ograve") return str ="Ò";
 | 
						|
		  if (str == "Ugrave") return str ="Ù";
 | 
						|
		  if (str == "agrave") return str ="à";
 | 
						|
		  if (str == "egrave") return str ="è";
 | 
						|
		  if (str == "eacuto") return str ="é";
 | 
						|
		  if (str == "igrave") return str ="ì";
 | 
						|
		  if (str == "ograve") return str ="ò";
 | 
						|
		  if (str == "ugrave") return str ="ù";
 | 
						|
 | 
						|
      const char tmp[2] = { cStart, '\0' };
 | 
						|
		  str.insert(tmp);
 | 
						|
    }
 | 
						|
	}
 | 
						|
	
 | 
						|
	return str;
 | 
						|
}
 | 
						|
 | 
						|
void WriteXmlString(ostream& outf, const char* str)
 | 
						|
{
 | 
						|
	for (int i = 0; str[i]; i++)
 | 
						|
	{
 | 
						|
		const char c = str[i];
 | 
						|
		if ((c < ' ' && c != '\n' && c != '\r') || strchr("<>/&", c) != NULL)
 | 
						|
		{
 | 
						|
			const unsigned int n = (unsigned char)c;
 | 
						|
			TString8 tmp; tmp.format("&#%02X;", n);
 | 
						|
			tmp.print_on(outf);
 | 
						|
		}
 | 
						|
		else
 | 
						|
			outf << c;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TXmlAttr
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TXmlAttr : public TString
 | 
						|
{
 | 
						|
public:
 | 
						|
	void Write(ostream& outf) const;
 | 
						|
	TXmlAttr(const char* str) : TString(str) { }
 | 
						|
};
 | 
						|
 | 
						|
void TXmlAttr::Write(ostream& outf) const
 | 
						|
{
 | 
						|
	outf << '"';
 | 
						|
  print_on(outf);
 | 
						|
	outf << '"';
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TXmlItem
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TXmlItem& TXmlItem::SetAttr(const char* strAttr, const char* strVal)
 | 
						|
{
 | 
						|
	if (m_Attributes == NULL)
 | 
						|
		m_Attributes = new TAssoc_array;
 | 
						|
  m_Attributes->remove(strAttr);
 | 
						|
  if (strVal && *strVal)
 | 
						|
    m_Attributes->add(strAttr, new TXmlAttr(strVal));
 | 
						|
	return *this;
 | 
						|
}
 | 
						|
 | 
						|
const TString& TXmlItem::GetAttr(const char* strAttr) const
 | 
						|
{
 | 
						|
	if (m_Attributes != NULL)
 | 
						|
	{
 | 
						|
	  const TXmlAttr* str = (const TXmlAttr*)m_Attributes->objptr(strAttr);
 | 
						|
		if (str != NULL)
 | 
						|
			return *str;
 | 
						|
	}
 | 
						|
	return EMPTY_STRING;
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem& TXmlItem::SetAttr(const char* strAttr, int n)
 | 
						|
{
 | 
						|
  TString16 str; 
 | 
						|
  if (n != 0) str << n;
 | 
						|
  return SetAttr(strAttr, str);
 | 
						|
}
 | 
						|
 | 
						|
int TXmlItem::GetIntAttr(const char* strAttr, int def) const
 | 
						|
{
 | 
						|
  const TString& str = GetAttr(strAttr);
 | 
						|
  if (str.not_empty())
 | 
						|
    def = atoi(str);
 | 
						|
  return def;
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem& TXmlItem::SetAttr(const char* strAttr, bool b)
 | 
						|
{
 | 
						|
  return SetAttr(strAttr, b ? "1" : "");
 | 
						|
}
 | 
						|
 | 
						|
bool TXmlItem::GetBoolAttr(const char* strAttr) const
 | 
						|
{
 | 
						|
  return !GetAttr(strAttr).blank();
 | 
						|
}
 | 
						|
 | 
						|
int TXmlItem::GetChildren() const
 | 
						|
{
 | 
						|
	int n = 0;
 | 
						|
	if (m_Children != NULL)
 | 
						|
		n = m_Children->items();
 | 
						|
	return n;
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem* TXmlItem::GetChild(size_t n) const
 | 
						|
{
 | 
						|
	TXmlItem* i = NULL;
 | 
						|
	if (m_Children != NULL)
 | 
						|
    i = (TXmlItem*)m_Children->objptr(n);
 | 
						|
	return i;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool TXmlItem::GetWord(istream& inf, TString& str) const
 | 
						|
{
 | 
						|
  str.cut(0);
 | 
						|
 | 
						|
  int cFirstChar = EOF;
 | 
						|
	while (!inf.eof())
 | 
						|
	{
 | 
						|
	  cFirstChar = inf.get();
 | 
						|
	  if (cFirstChar <= 0 || cFirstChar > ' ')
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	if (cFirstChar == EOF)
 | 
						|
		return false;
 | 
						|
  
 | 
						|
  str << char(cFirstChar);
 | 
						|
 | 
						|
	const bool bIsString = cFirstChar == '"' || cFirstChar == '\'';
 | 
						|
	if (!bIsString)
 | 
						|
	{
 | 
						|
		if (strchr("<=/>", cFirstChar) != NULL)
 | 
						|
			return true; // Simboli terminali
 | 
						|
 		if (cFirstChar == '&')
 | 
						|
  		str = EscapeSequence(cFirstChar, inf);
 | 
						|
	}
 | 
						|
 | 
						|
	while (!inf.eof())
 | 
						|
	{
 | 
						|
		int c = inf.get();
 | 
						|
    if (bIsString)
 | 
						|
		{
 | 
						|
			if (c >= '\0' && c <= ' ')
 | 
						|
				c = ' ';
 | 
						|
		  str << char(c);
 | 
						|
			if (c == cFirstChar)
 | 
						|
			  break;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			if (c >= '\0' && c <= ' ')
 | 
						|
				break;
 | 
						|
      if (strchr("<=/>", c))
 | 
						|
			{
 | 
						|
				inf.putback(char(c));
 | 
						|
				break;
 | 
						|
			}
 | 
						|
   		if (c == '&')
 | 
						|
    		str << EscapeSequence(c, inf);
 | 
						|
      else
 | 
						|
			  str << char(c);
 | 
						|
		}
 | 
						|
	}
 | 
						|
  return str.not_empty();
 | 
						|
}
 | 
						|
 | 
						|
int TXmlItem::ReadTag(istream& inf)
 | 
						|
{
 | 
						|
	TString str;
 | 
						|
  if (!GetWord(inf, str))
 | 
						|
		return -1;
 | 
						|
 | 
						|
	if (str[0] != '<')  // No tag = sequence of words
 | 
						|
	{
 | 
						|
		bool bFirstChar = true;
 | 
						|
 | 
						|
		while (!inf.eof())
 | 
						|
		{
 | 
						|
		  char c = inf.get();
 | 
						|
			if (c == '<')
 | 
						|
			{
 | 
						|
				inf.putback(c);
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			if (bFirstChar)
 | 
						|
			{
 | 
						|
        if (c != ' ')
 | 
						|
				  str << ' ';
 | 
						|
        bFirstChar = false;
 | 
						|
			}
 | 
						|
  		if (c == '&')
 | 
						|
				str << EscapeSequence(c, inf);
 | 
						|
			else
 | 
						|
			  str << c;
 | 
						|
		}
 | 
						|
		SetTag("");
 | 
						|
		SetText(str);  
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	TString name, tmp; 
 | 
						|
 | 
						|
	bool bChildrenFollow = true;
 | 
						|
	GetWord(inf, m_strTag);
 | 
						|
	if (m_strTag == "/")     // Sto leggendo un tag di chiusura del tipo </SOAP-ENV>
 | 
						|
	{
 | 
						|
		bChildrenFollow = false;
 | 
						|
    GetWord(inf, tmp);
 | 
						|
    m_strTag << tmp;
 | 
						|
	}
 | 
						|
 | 
						|
	while (GetWord(inf, name))
 | 
						|
	{
 | 
						|
    if (name[0] == '>')
 | 
						|
			return bChildrenFollow ? +1 : 0;
 | 
						|
 | 
						|
		if (name[0] == '/')
 | 
						|
		{
 | 
						|
			bChildrenFollow = false;
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		// Ho letto un nome di attributo
 | 
						|
		GetWord(inf, tmp);
 | 
						|
    if (tmp.empty() || tmp[0] != '=')
 | 
						|
			break;
 | 
						|
		// Leggo il valore dell'attributo
 | 
						|
    GetWord(inf, tmp);
 | 
						|
    const int len = tmp.len();
 | 
						|
    if (len >= 2 && (tmp[0] == '"' || tmp[0] == '\'') && tmp[len-1] == tmp[0])
 | 
						|
    { tmp.rtrim(1); tmp.ltrim(1); }
 | 
						|
 		SetAttr(name, tmp);
 | 
						|
	}
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem& TXmlItem::AddChild(TXmlItem* pItem)
 | 
						|
{
 | 
						|
	if (m_Children == NULL)
 | 
						|
    m_Children = new TArray;
 | 
						|
	if (pItem == NULL)
 | 
						|
    pItem = new TXmlItem;
 | 
						|
	m_Children->add(pItem);
 | 
						|
	return *pItem;
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem& TXmlItem::AddChild(const char* strTagName)
 | 
						|
{
 | 
						|
	TXmlItem& i = AddChild((TXmlItem*)NULL);
 | 
						|
	i.SetTag(strTagName);
 | 
						|
	return i;
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem& TXmlItem::AddSoapString(const char* name, const char* value, bool typized)
 | 
						|
{
 | 
						|
	TXmlItem& xmlVar = AddChild(name);
 | 
						|
	if (typized)
 | 
						|
	  xmlVar.SetAttr("xsi:type", "xsd:string");
 | 
						|
  xmlVar.AddChild("").SetText(value);
 | 
						|
	return xmlVar;
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem& TXmlItem::AddSoapInt(const char* name, int value, bool typized)
 | 
						|
{
 | 
						|
	TXmlItem& xmlVar = AddChild(name);
 | 
						|
	if (typized)
 | 
						|
  	xmlVar.SetAttr("xsi:type", "xsd:int");
 | 
						|
	TString16 str; str << value;
 | 
						|
  xmlVar.AddChild("").SetText(str);
 | 
						|
	return xmlVar;
 | 
						|
}
 | 
						|
 | 
						|
void TXmlItem::RemoveLastChild()
 | 
						|
{
 | 
						|
	if (m_Children != NULL)
 | 
						|
    m_Children->destroy(m_Children->last());
 | 
						|
}
 | 
						|
 | 
						|
bool TXmlItem::Read(istream& inf)
 | 
						|
{
 | 
						|
  Destroy();
 | 
						|
	const int res = ReadTag(inf);
 | 
						|
	if (res > 0)  // There are children ahead
 | 
						|
	{
 | 
						|
		while (!inf.eof())
 | 
						|
		{
 | 
						|
		  TXmlItem& item = AddChild("/");  // Add dummy child
 | 
						|
		  if (item.Read(inf))
 | 
						|
			{
 | 
						|
				if (item.m_strTag[0] == '/')
 | 
						|
					break;
 | 
						|
			}
 | 
						|
			else
 | 
						|
				break;
 | 
						|
		}
 | 
						|
		RemoveLastChild();                  // Remove dummy child
 | 
						|
	}
 | 
						|
	return res >= 0;
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem* TXmlItem::ForEach(XmlItemCallback cb, long jolly)
 | 
						|
{
 | 
						|
	if (cb(*this, jolly))
 | 
						|
		return this;
 | 
						|
 | 
						|
	for (int n = 0; ; n++)
 | 
						|
	{
 | 
						|
		TXmlItem* c = GetChild(n);
 | 
						|
		if (c == NULL)
 | 
						|
			break;
 | 
						|
		c = c->ForEach(cb, jolly);
 | 
						|
  	if (c)
 | 
						|
	  	return c;
 | 
						|
	}
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
static bool GetEnclosedTextCallback(TXmlItem& item, long jolly)
 | 
						|
{
 | 
						|
  TString* strText = (TString*)jolly;
 | 
						|
	const TString& str = item.GetText();
 | 
						|
	if (!str.empty())
 | 
						|
	{
 | 
						|
		if (!strText->empty())
 | 
						|
			*strText << " ";
 | 
						|
	  *strText << str;
 | 
						|
	}
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
bool TXmlItem::GetEnclosedText(TString& text) const
 | 
						|
{
 | 
						|
  text.cut(0);
 | 
						|
	((TXmlItem*)this)->ForEach(GetEnclosedTextCallback, (long)&text);
 | 
						|
	return text.not_empty();
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem& TXmlItem::AddEnclosedText(const char* str)
 | 
						|
{
 | 
						|
  TXmlItem* item = FindFirst("");
 | 
						|
	if (item == NULL)
 | 
						|
		item = &AddChild("");
 | 
						|
  if (item->m_strText == NULL)
 | 
						|
    item->SetText(str);
 | 
						|
  else
 | 
						|
    *item->m_strText << str;
 | 
						|
	return *item;
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem& operator<<(TXmlItem& item, const char* str)
 | 
						|
{
 | 
						|
	item.AddEnclosedText(str);
 | 
						|
	return item;
 | 
						|
}
 | 
						|
 | 
						|
void TXmlItem::Write(ostream& outf, int tab) const
 | 
						|
{
 | 
						|
	if (!GetTag().empty())
 | 
						|
	{
 | 
						|
		Spaces(outf, tab);
 | 
						|
	  outf << '<';
 | 
						|
    GetTag().print_on(outf);
 | 
						|
		if (m_Attributes != NULL)
 | 
						|
		{
 | 
						|
      TAssoc_array& ass = *m_Attributes;
 | 
						|
      FOR_EACH_ASSOC_OBJECT(ass, h, k, a)
 | 
						|
      {
 | 
						|
				outf << ' ' << k << '=';
 | 
						|
				const TXmlAttr* attr = (const TXmlAttr*)a;
 | 
						|
				attr->Write(outf);
 | 
						|
      }
 | 
						|
		}
 | 
						|
		if (GetChildren() > 0)
 | 
						|
		{
 | 
						|
			int n;
 | 
						|
			
 | 
						|
			outf << '>';
 | 
						|
      for (n = 0; ; n++)
 | 
						|
			{
 | 
						|
        TXmlItem* c = GetChild(n);
 | 
						|
				if (c == NULL)
 | 
						|
					break;
 | 
						|
				c->Write(outf, tab+1);
 | 
						|
			}
 | 
						|
			if (GetChild(n-1)->GetText().empty())
 | 
						|
			  Spaces(outf, tab);
 | 
						|
			outf << '<' << '/';
 | 
						|
      GetTag().print_on(outf);
 | 
						|
      outf << '>';
 | 
						|
		}
 | 
						|
		else
 | 
						|
		  outf << ' ' << '/' << '>';
 | 
						|
	}
 | 
						|
	else
 | 
						|
  {
 | 
						|
    WriteXmlString(outf, GetText());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TXmlItem::AsString(TString& str) const
 | 
						|
{
 | 
						|
	for (size_t nSize = 8192; ; nSize *= 2)
 | 
						|
	{
 | 
						|
	  char* buf = str.get_buffer(nSize); 
 | 
						|
		memset(buf, 0, nSize);
 | 
						|
#ifdef WIN32
 | 
						|
		ostrstream outf(buf, nSize);
 | 
						|
#else
 | 
						|
		ostringstream outf(buf);
 | 
						|
#endif
 | 
						|
 | 
						|
		Write(outf, 0);
 | 
						|
		if (buf[nSize-1] == '\0')
 | 
						|
			break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void TXmlItem::Save(const char* strFilename) const
 | 
						|
{
 | 
						|
	ofstream outf(strFilename);
 | 
						|
	Write(outf, 0);
 | 
						|
}
 | 
						|
 | 
						|
bool TXmlItem::Load(const char* strFilename)
 | 
						|
{
 | 
						|
  ifstream qry(strFilename);
 | 
						|
  return Read(qry);
 | 
						|
}
 | 
						|
 | 
						|
static bool FindFirstCallback(TXmlItem& item, long jolly)
 | 
						|
{
 | 
						|
  const char* strTag = (const char*)jolly;
 | 
						|
	return item.GetTag() == strTag;
 | 
						|
}
 | 
						|
 | 
						|
void TXmlItem::Destroy()
 | 
						|
{
 | 
						|
  m_strTag.cut(0);
 | 
						|
  if (m_strText)
 | 
						|
    m_strText->cut(0);
 | 
						|
	if (m_Attributes)
 | 
						|
    m_Attributes->destroy();
 | 
						|
	if (m_Children)
 | 
						|
    m_Children->destroy();
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem* TXmlItem::FindFirst(const char* strTag) const
 | 
						|
{
 | 
						|
	return ((TXmlItem*)this)->ForEach(FindFirstCallback, (long)strTag);
 | 
						|
}
 | 
						|
 | 
						|
TXmlItem* TXmlItem::FindFirstChild(const char* strTag) const
 | 
						|
{
 | 
						|
	for (int i = 0; i < GetChildren(); i++)
 | 
						|
  {
 | 
						|
    TXmlItem* c = GetChild(i);
 | 
						|
    if (c->GetTag() == strTag)
 | 
						|
      return c;
 | 
						|
  }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
TXmlItem::TXmlItem()
 | 
						|
        : m_strTag(15), m_strText(NULL), m_Attributes(NULL), m_Children(NULL)
 | 
						|
{ }
 | 
						|
 | 
						|
TXmlItem::~TXmlItem()
 | 
						|
{ 
 | 
						|
  if (m_strText)
 | 
						|
    delete m_strText;
 | 
						|
	if (m_Attributes)
 | 
						|
		delete m_Attributes;
 | 
						|
	if (m_Children)
 | 
						|
		delete m_Children;
 | 
						|
} 
 | 
						|
 |