CLAM-Development  1.4.0
LibXmlDomDocumentHandler.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 #ifndef _LibXmlDomDocumentHandler_hxx_
22 #define _LibXmlDomDocumentHandler_hxx_
23 
26 #include "LibXmlDomReader.hxx"
27 #include "LibXmlDomWriter.hxx"
28 
29 
30 #include <libxml++/libxml++.h>
31 
32 namespace CLAM
33 {
34 class LibXmlDomReadingContext;
35 class LibXmlDomWritingContext;
41 {
42 public:
46  {
47  return _currentReadContext;
48  }
50  {
51  _currentReadContext = context;
52  }
54  {
55  return _currentWriteContext;
56  }
58  {
59  _currentWriteContext = context;
60  }
61 private:
62  ReadingContext * _currentReadContext;
63  WritingContext * _currentWriteContext;
64  xmlpp::Document * _document;
65  xmlpp::Element * _selection;
66  xmlpp::DomParser * _parser;
67 public:
69  {
70  _document = 0;
71  _selection = 0;
72  _parser = 0;
73  }
75  {
76  releaseIfAnyDocument();
77  }
78  void setDocument(xmlpp::Document * document)
79  {
80  _document = document;
81  _selection = _document->get_root_node();
82  }
83  void selectPath(const char * path)
84  {
85  if (path[0]!='/')
86  _selection = recursiveSelection(_selection, path, 0);
87  else
88  _selection = absoluteSelection(path);
89  return;
90  }
91  xmlpp::Element * getSelection()
92  {
93  return _selection;
94  }
95  void create(const char * rootName)
96  {
97  releaseIfAnyDocument();
98 
99  xmlpp::Document * domDoc = new xmlpp::Document;
100  domDoc->create_root_node(rootName);
101  setDocument(domDoc);
102  }
103  void read(std::istream & stream)
104  {
105  LibXmlDomReader reader;
106  xmlpp::Document * domDoc;
107  domDoc = reader.read(stream);
108  setDocument(domDoc);
109  _parser = reader.adoptParser();
110  }
111  void writeDocument(std::ostream & os, bool useIndentation=false)
112  {
113  LibXmlDomWriter writer;
114  writer.DoIndentedFormat(useIndentation);
115  writer.write(os,_document);
116  }
117  void writeSelection(std::ostream & os, bool useIndentation=false)
118  {
119  LibXmlDomWriter writer;
120  writer.DoIndentedFormat(useIndentation);
121  writer.write(os,_selection);
122  }
123 private:
124  void releaseIfAnyDocument()
125  {
126  if (!_document) return;
127 
128  if (_parser)
129  delete _parser;
130  else
131  delete _document;
132  _parser=0;
133  _document=0;
134  }
135  xmlpp::Element * absoluteSelection(const std::string & path)
136  {
137  xmlpp::Element * root = _document->get_root_node();
138  unsigned int nextSlash = std::string(path).find('/',1);
139  std::string rootStep = std::string(path).substr(1,nextSlash-1);
140  std::string rootName = root->get_name();
141  if (rootStep=="") return root;
142 
143  if (rootName== rootStep)
144  return recursiveSelection(root, path, nextSlash+1);
145 
146  throw XmlStorageErr("Wrong root name, expected '"+rootStep+"' but found '"+rootName+"'");
147  }
148  xmlpp::Element * recursiveSelection(xmlpp::Element * current, const std::string & path, unsigned int pos)
149  {
150  if (pos >= path.length()) return current;
151  unsigned int slashPosition = path.find('/', pos);
152  unsigned int stepSize =
153  slashPosition == std::string::npos ?
154  std::string::npos : slashPosition-pos;
155  std::string step = path.substr(pos, stepSize);
156  xmlpp::Element::NodeList children = current->get_children();
157  for (
158  xmlpp::Element::NodeList::iterator child = children.begin();
159  child!=children.end();
160  child++)
161  {
162  xmlpp::Element * element = dynamic_cast<xmlpp::Element*>(*child);
163  if (!element) continue;
164  std::string nodeName= element->get_name();
165  if (nodeName != step) continue;
166  if (slashPosition==std::string::npos) return element;
167  return recursiveSelection(element, path, slashPosition+1);
168  }
169  std::string msg = "Wrong path step '" + step + "'";
170  throw XmlStorageErr(msg);
171  }
172 };
173 
174 
175 }
176 
181 #endif//_LibXmlDomDocumentHandler_hxx_
182