1 | // |
2 | // DOMSerializer.cpp |
3 | // |
4 | // Library: XML |
5 | // Package: DOM |
6 | // Module: DOMSerializer |
7 | // |
8 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/DOM/DOMSerializer.h" |
16 | #include "Poco/DOM/Document.h" |
17 | #include "Poco/DOM/DocumentType.h" |
18 | #include "Poco/DOM/DocumentFragment.h" |
19 | #include "Poco/DOM/Element.h" |
20 | #include "Poco/DOM/Attr.h" |
21 | #include "Poco/DOM/Text.h" |
22 | #include "Poco/DOM/CDATASection.h" |
23 | #include "Poco/DOM/Comment.h" |
24 | #include "Poco/DOM/ProcessingInstruction.h" |
25 | #include "Poco/DOM/Entity.h" |
26 | #include "Poco/DOM/Notation.h" |
27 | #include "Poco/DOM/NamedNodeMap.h" |
28 | #include "Poco/DOM/AutoPtr.h" |
29 | #include "Poco/SAX/EntityResolver.h" |
30 | #include "Poco/SAX/DTDHandler.h" |
31 | #include "Poco/SAX/ContentHandler.h" |
32 | #include "Poco/SAX/LexicalHandler.h" |
33 | #include "Poco/SAX/AttributesImpl.h" |
34 | #include "Poco/SAX/ErrorHandler.h" |
35 | #include "Poco/SAX/SAXException.h" |
36 | |
37 | |
38 | namespace Poco { |
39 | namespace XML { |
40 | |
41 | |
42 | const XMLString DOMSerializer::CDATA = toXMLString("CDATA" ); |
43 | |
44 | |
45 | DOMSerializer::DOMSerializer(): |
46 | _pEntityResolver(0), |
47 | _pDTDHandler(0), |
48 | _pContentHandler(0), |
49 | _pErrorHandler(0), |
50 | _pDeclHandler(0), |
51 | _pLexicalHandler(0) |
52 | { |
53 | } |
54 | |
55 | |
56 | DOMSerializer::~DOMSerializer() |
57 | { |
58 | } |
59 | |
60 | |
61 | void DOMSerializer::setEntityResolver(EntityResolver* pEntityResolver) |
62 | { |
63 | _pEntityResolver = pEntityResolver; |
64 | } |
65 | |
66 | |
67 | EntityResolver* DOMSerializer::getEntityResolver() const |
68 | { |
69 | return _pEntityResolver; |
70 | } |
71 | |
72 | |
73 | void DOMSerializer::setDTDHandler(DTDHandler* pDTDHandler) |
74 | { |
75 | _pDTDHandler = pDTDHandler; |
76 | } |
77 | |
78 | |
79 | DTDHandler* DOMSerializer::getDTDHandler() const |
80 | { |
81 | return _pDTDHandler; |
82 | } |
83 | |
84 | |
85 | void DOMSerializer::setContentHandler(ContentHandler* pContentHandler) |
86 | { |
87 | _pContentHandler = pContentHandler; |
88 | } |
89 | |
90 | |
91 | ContentHandler* DOMSerializer::getContentHandler() const |
92 | { |
93 | return _pContentHandler; |
94 | } |
95 | |
96 | |
97 | void DOMSerializer::setErrorHandler(ErrorHandler* pErrorHandler) |
98 | { |
99 | _pErrorHandler = pErrorHandler; |
100 | } |
101 | |
102 | |
103 | ErrorHandler* DOMSerializer::getErrorHandler() const |
104 | { |
105 | return _pErrorHandler; |
106 | } |
107 | |
108 | |
109 | void DOMSerializer::setFeature(const XMLString& featureId, bool state) |
110 | { |
111 | if (featureId == XMLReader::FEATURE_NAMESPACES) |
112 | throw SAXNotSupportedException(fromXMLString(XMLReader::FEATURE_NAMESPACES)); |
113 | else if (featureId == XMLReader::FEATURE_NAMESPACE_PREFIXES) |
114 | throw SAXNotSupportedException(fromXMLString(XMLReader::FEATURE_NAMESPACE_PREFIXES)); |
115 | else |
116 | throw SAXNotRecognizedException(fromXMLString(featureId)); |
117 | } |
118 | |
119 | |
120 | bool DOMSerializer::getFeature(const XMLString& featureId) const |
121 | { |
122 | if (featureId == XMLReader::FEATURE_NAMESPACES) |
123 | throw SAXNotSupportedException(fromXMLString(XMLReader::FEATURE_NAMESPACES)); |
124 | else if (featureId == XMLReader::FEATURE_NAMESPACE_PREFIXES) |
125 | throw SAXNotSupportedException(fromXMLString(XMLReader::FEATURE_NAMESPACE_PREFIXES)); |
126 | else |
127 | throw SAXNotRecognizedException(fromXMLString(featureId)); |
128 | } |
129 | |
130 | |
131 | void DOMSerializer::setProperty(const XMLString& propertyId, const XMLString& value) |
132 | { |
133 | if (propertyId == XMLReader::PROPERTY_DECLARATION_HANDLER || propertyId == XMLReader::PROPERTY_LEXICAL_HANDLER) |
134 | throw SAXNotSupportedException(std::string("property does not take a string value: " ) + fromXMLString(propertyId)); |
135 | else |
136 | throw SAXNotRecognizedException(fromXMLString(propertyId)); |
137 | } |
138 | |
139 | |
140 | void DOMSerializer::setProperty(const XMLString& propertyId, void* value) |
141 | { |
142 | if (propertyId == XMLReader::PROPERTY_DECLARATION_HANDLER) |
143 | _pDeclHandler = reinterpret_cast<DeclHandler*>(value); |
144 | else if (propertyId == XMLReader::PROPERTY_LEXICAL_HANDLER) |
145 | _pLexicalHandler = reinterpret_cast<LexicalHandler*>(value); |
146 | else throw SAXNotRecognizedException(fromXMLString(propertyId)); |
147 | } |
148 | |
149 | |
150 | void* DOMSerializer::getProperty(const XMLString& propertyId) const |
151 | { |
152 | if (propertyId == XMLReader::PROPERTY_DECLARATION_HANDLER) |
153 | return _pDeclHandler; |
154 | else if (propertyId == XMLReader::PROPERTY_LEXICAL_HANDLER) |
155 | return _pLexicalHandler; |
156 | else throw SAXNotSupportedException(fromXMLString(propertyId)); |
157 | } |
158 | |
159 | |
160 | void DOMSerializer::serialize(const Node* pNode) |
161 | { |
162 | poco_check_ptr (pNode); |
163 | |
164 | handleNode(pNode); |
165 | } |
166 | |
167 | |
168 | void DOMSerializer::parse(InputSource* pSource) |
169 | { |
170 | throw XMLException("The DOMSerializer cannot parse an InputSource" ); |
171 | } |
172 | |
173 | |
174 | void DOMSerializer::parse(const XMLString& systemId) |
175 | { |
176 | throw XMLException("The DOMSerializer cannot parse from a system identifier" ); |
177 | } |
178 | |
179 | |
180 | void DOMSerializer::parseMemoryNP(const char* xml, std::size_t size) |
181 | { |
182 | throw XMLException("The DOMSerializer cannot parse from memory" ); |
183 | } |
184 | |
185 | |
186 | void DOMSerializer::iterate(const Node* pNode) const |
187 | { |
188 | while (pNode) |
189 | { |
190 | handleNode(pNode); |
191 | pNode = pNode->nextSibling(); |
192 | } |
193 | } |
194 | |
195 | |
196 | void DOMSerializer::handleNode(const Node* pNode) const |
197 | { |
198 | switch (pNode->nodeType()) |
199 | { |
200 | case Node::ELEMENT_NODE: |
201 | handleElement(static_cast<const Element*>(pNode)); |
202 | break; |
203 | case Node::TEXT_NODE: |
204 | handleCharacterData(static_cast<const Text*>(pNode)); |
205 | break; |
206 | case Node::CDATA_SECTION_NODE: |
207 | handleCDATASection(static_cast<const CDATASection*>(pNode)); |
208 | break; |
209 | case Node::ENTITY_NODE: |
210 | handleEntity(static_cast<const Entity*>(pNode)); |
211 | break; |
212 | case Node::PROCESSING_INSTRUCTION_NODE: |
213 | handlePI(static_cast<const ProcessingInstruction*>(pNode)); |
214 | break; |
215 | case Node::COMMENT_NODE: |
216 | handleComment(static_cast<const Comment*>(pNode)); |
217 | break; |
218 | case Node::DOCUMENT_NODE: |
219 | handleDocument(static_cast<const Document*>(pNode)); |
220 | break; |
221 | case Node::DOCUMENT_TYPE_NODE: |
222 | handleDocumentType(static_cast<const DocumentType*>(pNode)); |
223 | break; |
224 | case Node::DOCUMENT_FRAGMENT_NODE: |
225 | handleFragment(static_cast<const DocumentFragment*>(pNode)); |
226 | break; |
227 | case Node::NOTATION_NODE: |
228 | handleNotation(static_cast<const Notation*>(pNode)); |
229 | break; |
230 | } |
231 | } |
232 | |
233 | |
234 | void DOMSerializer::handleElement(const Element* pElement) const |
235 | { |
236 | if (_pContentHandler) |
237 | { |
238 | AutoPtr<NamedNodeMap> pAttrs = pElement->attributes(); |
239 | AttributesImpl saxAttrs; |
240 | for (unsigned long i = 0; i < pAttrs->length(); ++i) |
241 | { |
242 | Attr* pAttr = static_cast<Attr*>(pAttrs->item(i)); |
243 | saxAttrs.addAttribute(pAttr->namespaceURI(), pAttr->localName(), pAttr->nodeName(), CDATA, pAttr->value(), pAttr->specified()); |
244 | } |
245 | _pContentHandler->startElement(pElement->namespaceURI(), pElement->localName(), pElement->tagName(), saxAttrs); |
246 | } |
247 | iterate(pElement->firstChild()); |
248 | if (_pContentHandler) |
249 | _pContentHandler->endElement(pElement->namespaceURI(), pElement->localName(), pElement->tagName()); |
250 | } |
251 | |
252 | |
253 | void DOMSerializer::handleCharacterData(const Text* pText) const |
254 | { |
255 | if (_pContentHandler) |
256 | { |
257 | const XMLString& data = pText->data(); |
258 | _pContentHandler->characters(data.c_str(), 0, (int) data.length()); |
259 | } |
260 | } |
261 | |
262 | |
263 | void DOMSerializer::handleComment(const Comment* ) const |
264 | { |
265 | if (_pLexicalHandler) |
266 | { |
267 | const XMLString& data = pComment->data(); |
268 | _pLexicalHandler->comment(data.c_str(), 0, (int) data.length()); |
269 | } |
270 | } |
271 | |
272 | |
273 | void DOMSerializer::handlePI(const ProcessingInstruction* pPI) const |
274 | { |
275 | if (_pContentHandler) _pContentHandler->processingInstruction(pPI->target(), pPI->data()); |
276 | } |
277 | |
278 | |
279 | void DOMSerializer::handleCDATASection(const CDATASection* pCDATA) const |
280 | { |
281 | if (_pLexicalHandler) _pLexicalHandler->startCDATA(); |
282 | handleCharacterData(pCDATA); |
283 | if (_pLexicalHandler) _pLexicalHandler->endCDATA(); |
284 | } |
285 | |
286 | |
287 | void DOMSerializer::handleDocument(const Document* pDocument) const |
288 | { |
289 | if (_pContentHandler) _pContentHandler->startDocument(); |
290 | const DocumentType* pDoctype = pDocument->doctype(); |
291 | if (pDoctype) handleDocumentType(pDoctype); |
292 | iterate(pDocument->firstChild()); |
293 | if (_pContentHandler) _pContentHandler->endDocument(); |
294 | } |
295 | |
296 | |
297 | void DOMSerializer::handleDocumentType(const DocumentType* pDocumentType) const |
298 | { |
299 | if (_pLexicalHandler) _pLexicalHandler->startDTD(pDocumentType->name(), pDocumentType->publicId(), pDocumentType->systemId()); |
300 | iterate(pDocumentType->firstChild()); |
301 | if (_pLexicalHandler) _pLexicalHandler->endDTD(); |
302 | } |
303 | |
304 | |
305 | void DOMSerializer::handleFragment(const DocumentFragment* pFragment) const |
306 | { |
307 | iterate(pFragment->firstChild()); |
308 | } |
309 | |
310 | |
311 | void DOMSerializer::handleNotation(const Notation* pNotation) const |
312 | { |
313 | if (_pDTDHandler) _pDTDHandler->notationDecl(pNotation->nodeName(), &pNotation->publicId(), &pNotation->systemId()); |
314 | } |
315 | |
316 | |
317 | void DOMSerializer::handleEntity(const Entity* pEntity) const |
318 | { |
319 | if (_pDTDHandler) _pDTDHandler->unparsedEntityDecl(pEntity->nodeName(), &pEntity->publicId(), pEntity->systemId(), pEntity->notationName()); |
320 | } |
321 | |
322 | |
323 | } } // namespace Poco::XML |
324 | |