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>
45namespace 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"
58namespace 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
144namespace 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:42
Definition XmlAdapter.h:148