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
38namespace Poco {
39namespace XML {
40
41
42const XMLString DOMSerializer::CDATA = toXMLString("CDATA");
43
44
45DOMSerializer::DOMSerializer():
46 _pEntityResolver(0),
47 _pDTDHandler(0),
48 _pContentHandler(0),
49 _pErrorHandler(0),
50 _pDeclHandler(0),
51 _pLexicalHandler(0)
52{
53}
54
55
56DOMSerializer::~DOMSerializer()
57{
58}
59
60
61void DOMSerializer::setEntityResolver(EntityResolver* pEntityResolver)
62{
63 _pEntityResolver = pEntityResolver;
64}
65
66
67EntityResolver* DOMSerializer::getEntityResolver() const
68{
69 return _pEntityResolver;
70}
71
72
73void DOMSerializer::setDTDHandler(DTDHandler* pDTDHandler)
74{
75 _pDTDHandler = pDTDHandler;
76}
77
78
79DTDHandler* DOMSerializer::getDTDHandler() const
80{
81 return _pDTDHandler;
82}
83
84
85void DOMSerializer::setContentHandler(ContentHandler* pContentHandler)
86{
87 _pContentHandler = pContentHandler;
88}
89
90
91ContentHandler* DOMSerializer::getContentHandler() const
92{
93 return _pContentHandler;
94}
95
96
97void DOMSerializer::setErrorHandler(ErrorHandler* pErrorHandler)
98{
99 _pErrorHandler = pErrorHandler;
100}
101
102
103ErrorHandler* DOMSerializer::getErrorHandler() const
104{
105 return _pErrorHandler;
106}
107
108
109void 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
120bool 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
131void 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
140void 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
150void* 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
160void DOMSerializer::serialize(const Node* pNode)
161{
162 poco_check_ptr (pNode);
163
164 handleNode(pNode);
165}
166
167
168void DOMSerializer::parse(InputSource* pSource)
169{
170 throw XMLException("The DOMSerializer cannot parse an InputSource");
171}
172
173
174void DOMSerializer::parse(const XMLString& systemId)
175{
176 throw XMLException("The DOMSerializer cannot parse from a system identifier");
177}
178
179
180void DOMSerializer::parseMemoryNP(const char* xml, std::size_t size)
181{
182 throw XMLException("The DOMSerializer cannot parse from memory");
183}
184
185
186void DOMSerializer::iterate(const Node* pNode) const
187{
188 while (pNode)
189 {
190 handleNode(pNode);
191 pNode = pNode->nextSibling();
192 }
193}
194
195
196void 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
234void 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
253void 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
263void DOMSerializer::handleComment(const Comment* pComment) 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
273void DOMSerializer::handlePI(const ProcessingInstruction* pPI) const
274{
275 if (_pContentHandler) _pContentHandler->processingInstruction(pPI->target(), pPI->data());
276}
277
278
279void DOMSerializer::handleCDATASection(const CDATASection* pCDATA) const
280{
281 if (_pLexicalHandler) _pLexicalHandler->startCDATA();
282 handleCharacterData(pCDATA);
283 if (_pLexicalHandler) _pLexicalHandler->endCDATA();
284}
285
286
287void 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
297void 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
305void DOMSerializer::handleFragment(const DocumentFragment* pFragment) const
306{
307 iterate(pFragment->firstChild());
308}
309
310
311void DOMSerializer::handleNotation(const Notation* pNotation) const
312{
313 if (_pDTDHandler) _pDTDHandler->notationDecl(pNotation->nodeName(), &pNotation->publicId(), &pNotation->systemId());
314}
315
316
317void 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