CiftiLib
A C++ library for CIFTI-2 and CIFTI-1 files
XmlAdapter.h
1 #ifndef __XML_ADAPTER_H__
2 #define __XML_ADAPTER_H__
3 
4 /*LICENSE_START*/
5 /*
6  * Copyright (c) 2014, Washington University School of Medicine
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modification,
10  * are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "AString.h"
32 #include "CiftiException.h"
33 
34 #include <map>
35 #include <vector>
36 
37 #ifdef __XML_ADAPTER_H_HAVE_IMPL__
38 #undef __XML_ADAPTER_H_HAVE_IMPL__
39 #endif
40 
41 #ifdef CIFTILIB_USE_QT
42 #define __XML_ADAPTER_H_HAVE_IMPL__
43 #include <QXmlStreamReader>
44 #include <QXmlStreamWriter>
45 namespace cifti
46 {
47  typedef QXmlStreamReader XmlReader;
48  typedef QXmlStreamWriter XmlWriter;
49 }
50 #endif //CIFTILIB_USE_QT
51 
52 #ifdef CIFTILIB_USE_XMLPP
53 #define __XML_ADAPTER_H_HAVE_IMPL__
54 #include "libxml++/libxml++.h"
55 #include "libxml++/parsers/textreader.h"
56 #include "libxml/xmlwriter.h"
57 #include "libxml/xmlstring.h"
58 namespace cifti
59 {
60  typedef xmlpp::TextReader XmlReader;
61  class XmlWriter
62  {//write our own wrapper for the C writing API, as libxml++ doesn't wrap it
63  xmlTextWriterPtr m_xmlPtr;
64  xmlBufferPtr m_bufPtr;
65  std::vector<AString> m_elementStack;//track element names for better error messages
66  public:
67  XmlWriter()
68  {//only support writing to memory
69  m_bufPtr = xmlBufferCreate();
70  if (m_bufPtr == NULL) throw CiftiException("error creating xml buffer");
71  m_xmlPtr = xmlNewTextWriterMemory(m_bufPtr, 0);
72  if (m_xmlPtr == NULL)
73  {
74  xmlBufferFree(m_bufPtr);
75  throw CiftiException("error creating xml writer");
76  }
77  if (xmlTextWriterSetIndent(m_xmlPtr, 1) != 0 || xmlTextWriterSetIndentString(m_xmlPtr, BAD_CAST " ") != 0)
78  {
79  throw CiftiException("error setting xml writer indentation");
80  }
81  }
82  ~XmlWriter()
83  {
84  xmlFreeTextWriter(m_xmlPtr);
85  xmlBufferFree(m_bufPtr);
86  }
87  void writeStartDocument()//copy a subset of the QXmlStreamWriter interface, so we don't have to rewrite much (any?) xml writing code
88  {
89  if (xmlTextWriterStartDocument(m_xmlPtr, NULL, NULL, NULL) == -1) throw CiftiException("error writing document start");
90  }
91  void writeEndDocument()
92  {
93  if (xmlTextWriterEndDocument(m_xmlPtr) == -1) throw CiftiException("error writing document end");
94  m_elementStack.clear();
95  }
96  void writeStartElement(const AString& name)
97  {
98  if (xmlTextWriterStartElement(m_xmlPtr, BAD_CAST ASTRING_UTF8_RAW(name)) == -1) throw CiftiException("error writing " + name + " element");
99  m_elementStack.push_back(name);
100  }
101  void writeEndElement()
102  {
103  if (m_elementStack.empty()) throw CiftiException("internal error: attempted writing end element outside root element");
104  if (xmlTextWriterEndElement(m_xmlPtr) == -1) throw CiftiException("error writing end element for " + m_elementStack.back());
105  m_elementStack.pop_back();
106  }
107  void writeCharacters(const AString& text)
108  {
109  if (xmlTextWriterWriteString(m_xmlPtr, BAD_CAST ASTRING_UTF8_RAW(text)) == -1) throw CiftiException("error writing element text");
110  }
111  void writeTextElement(const AString& name, const AString& text)
112  {
113  if (xmlTextWriterWriteElement(m_xmlPtr, BAD_CAST ASTRING_UTF8_RAW(name), BAD_CAST ASTRING_UTF8_RAW(text)) == -1)
114  {
115  throw CiftiException("error writing " + name + " element");
116  }
117  }
118  void writeAttribute(const AString& name, const AString& text)
119  {
120  if (m_elementStack.empty()) throw CiftiException("internal error: attempted writing attribute outside root element");
121  if (xmlTextWriterWriteAttribute(m_xmlPtr, BAD_CAST ASTRING_UTF8_RAW(name), BAD_CAST ASTRING_UTF8_RAW(text)) == -1)
122  {
123  throw CiftiException("error writing " + name + " attribute of " + m_elementStack.back() + " element");
124  }
125  }
126  std::vector<char> getXmlData() const
127  {
128  std::vector<char> ret(m_bufPtr->use);//this includes the null terminator?
129  for (unsigned int i = 0; i < m_bufPtr->use; ++i)
130  {
131  ret[i] = m_bufPtr->content[i];
132  }
133  return ret;
134  }
135  };
136 
137 }
138 #endif //CIFTILIB_USE_XMLPP
139 
140 #ifndef __XML_ADAPTER_H_HAVE_IMPL__
141 #error "you must define either CIFTILIB_USE_QT or CIFTILIB_USE_XMLPP to select what XML implementation to use"
142 #endif
143 
144 namespace cifti
145 {
146  //helper functions that exist for all xml libraries
148  {
150  {
151  OptionalStatus() { present = false; }
152  bool present;
153  AString value;
154  };
155  std::vector<AString> mandatoryVals;
156  std::vector<OptionalStatus> optionalVals;
157  };
158 
159  AString XmlReader_readElementText(XmlReader& xml);
160  bool XmlReader_readNextStartElement(XmlReader& xml);
161  AString XmlReader_elementName(XmlReader& xml);
162  XmlAttributesResult XmlReader_parseAttributes(XmlReader& xml, const std::vector<AString>& mandatoryNames, const std::vector<AString>& optionalNames = std::vector<AString>());
163  bool XmlReader_checkEndElement(XmlReader& xml, const AString& elementName);//for use in asserts at end of element parsing functions
164 }
165 
166 #endif //__XML_ADAPTER_H__
namespace for all CiftiLib functionality
Definition: CiftiBrainModelsMap.h:41
Definition: XmlAdapter.h:149
Definition: XmlAdapter.h:147