/* * e4xmloutputprocessor.cpp -- * * This file contains the implementation of the e4_XMLOutputProcessor * class defined in e4xml.h. * * Authors: Jacob Levy and Jean-Claude Wippler. * jyl@best.com jcw@equi4.com * * Copyright: JYL Software, Inc., (c) 2000-2003. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF * JYL SOFTWARE INC. IS MADE AWARE OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "e4xml.h" /* *************************************************************************** * * * Implementation of e4_XMLOutputProcessor class: * * * *************************************************************************** */ /* * Default constructor */ e4_XMLOutputProcessor::e4_XMLOutputProcessor() : generator(NULL) { } /* * Constructor with parser argument. */ e4_XMLOutputProcessor::e4_XMLOutputProcessor(e4_XMLGenerator *g) : generator(g) { } /* * Destructor. */ e4_XMLOutputProcessor::~e4_XMLOutputProcessor() { /* * Nothing to do. */ } /* * Handle the start of output processing. */ bool e4_XMLOutputProcessor::ProcessOutputBegin(const char *se, e4_Node &sn, bool firstTime) { /* * Default implementation doesn't handle multi-invocation generation, so * return error if not first time. */ return firstTime; } /* * Handle the end of output processing. */ bool e4_XMLOutputProcessor::ProcessOutputEnd(bool firstTime) { /* * Default implementation doesn't handle multi-invocation generation, so * return error if not first time. */ return firstTime; } /* * Process a node which is a back reference to another node. */ bool e4_XMLOutputProcessor::ProcessBackRefNode(const e4_Node &n, const char *elementName, int nodeId, int vertexUserData) { *outstream << "<__nodebackref__"; *outstream << " __nodeid__=\"" << nodeId << "\""; *outstream << " __name__=\"" << elementName << "\""; if ((vertexUserData != 0) && (generator->IsExportXML() == false)) { *outstream << " __vertexuserdata__=\"" << vertexUserData << "\""; } *outstream << "/>\n"; return true; } /* * Process a normal node. * * On input, if this node has parents and could be part of a cyclic * graph, nodeId will be some value other than -1. */ bool e4_XMLOutputProcessor::ProcessNodeBegin(const e4_Node &n, const char *elementName, int nodeId, int vertexUserData, e4_DString &dsAttrs, bool hasVertices) { int nodeUserData; *outstream << "<" << elementName; /* * If exportPureXML == false, include the user data attached to this * node and to the vertex in the output. * * If exportPureXML == true, then suppress this part of the generated * XML so that it corresponds exactly to XML input that could have been * used to create this node. */ if (!generator->IsExportXML()) { if (nodeId != -1) { *outstream << " __nodeid__=\"" << nodeId << "\""; } n.GetUserData(nodeUserData); if (nodeUserData != 0) { *outstream << " __nodeuserdata__=\"" << nodeUserData << "\""; } if (vertexUserData != 0) { *outstream << " __vertexuserdata__=\"" << vertexUserData << "\""; } } /* * If there are attributes to output for this node then produce them * on the output stream. */ if (dsAttrs.Length()) { *outstream << dsAttrs.Get(); } /* * Finally, if there are no vertices that follow, generate an empty * XML element. */ if (!hasVertices) { *outstream << "/"; } *outstream << ">\n"; return (true); } /* * Produce the node-end bracket in the output. */ bool e4_XMLOutputProcessor::ProcessNodeEnd(const e4_Node &n, const char *elementName, bool hasVertices) { /* * If this node had vertices generated inside it, close off the node's * wrapping element. */ if (hasVertices) { *outstream << "\n"; } return (true); } /* * Process a vertex. */ bool e4_XMLOutputProcessor::ProcessVertex(const e4_Vertex& v) { int vi, nbytes, ud; double vf; const void* bytes; const char* s; char *base64str = NULL; /* * Generate vertex element and mandatory vertex name. */ *outstream << "<__vertex__ name=\"" << v.Name() << "\""; /* * Produce the type and value attributes. */ switch (v.Type()) { case E4_VTNODE: /* * Should not occur! */ break; case E4_VTINT: (void) v.Get(vi); *outstream << " type=\"int\" value=\"" << vi << "\""; break; case E4_VTDOUBLE: (void) v.Get(vf); *outstream << " type=\"double\" value=\"" << vf << "\""; break; case E4_VTSTRING: (void) v.Get(s); *outstream << " type=\"string\" length=\""; *outstream << (int) strlen(s) << "\""; break; case E4_VTBINARY: (void) v.Get(bytes, nbytes); base64str = base64_encode((byte *) bytes, nbytes); *outstream << " type=\"binary\" length=\""; *outstream << (int) strlen(base64str) << "\""; break; default: /* * Should not occur! */ break; } if (generator->IsExportXML() == false) { (void) v.GetUserData(ud); if (ud != 0) { *outstream << " __vertexuserdata__=\"" << ud << "\""; } } /* * If we are producing a string or binary value output, produce * the actual value as PCDATA. */ if (v.Type() == E4_VTSTRING) { *outstream << ">" << s << "\n"; } else if (v.Type() == E4_VTBINARY) { *outstream << ">" << base64str << "\n"; } else { *outstream << "/>\n"; } /* * Free the buffer returned by base64_encode. */ if (base64str != NULL) { free(base64str); } return true; } /* * Process a comment in the output stream. */ bool e4_XMLOutputProcessor::ProcessComment(const char *comment) { *outstream << "<-- " << comment << " -->\n"; return true; } /* * Process character data in the output stream. */ bool e4_XMLOutputProcessor::ProcessCharData(const char *data) { *outstream << data << '\n'; return true; } /* * Process CDATA in the output stream. */ bool e4_XMLOutputProcessor::ProcessCDATA(const char *data) { *outstream << "\n"; return true; } /* * Process a processing instruction in the output stream. */ bool e4_XMLOutputProcessor::ProcessInstructions(const char *target, const char *data) { *outstream << "\n"; return true; } /* * Process an XML declaration in the output stream. */ bool e4_XMLOutputProcessor::ProcessXMLDeclaration(const char *version, const char *encoding, int standalone) { *outstream << "\n"; return true; } /* * Process the begin bracket for a DTD declaration. */ bool e4_XMLOutputProcessor::ProcessDTDBegin(const char *doctypename, const char *sysid, const char *pubid, int hasinternalsubset) { *outstream << "\n"; return true; } /* * Produce output for an unparsed entity declaration. */ bool e4_XMLOutputProcessor::ProcessUnparsedEntity(const char *entityname, const char *base, const char *systemid, const char *publicid, const char *notationname) { /* * Since I don't really know what to produce, just ignore and * return false to indicate we failed. */ return false; } /* * Produce output for a skipped entity. */ bool e4_XMLOutputProcessor::ProcessSkippedEntity(const char *entityname, int isparameterentity) { /* * Since I don't really know what to produce, just ignore and * return false to indicate we failed. */ return false; } /* * Produce output for a notation declaration */ bool e4_XMLOutputProcessor::ProcessNotationDecl(const char *notationname, const char *base, const char *systemid, const char *publicid) { /* * Since I don't really know what to produce, just ignore and * return false to indicate we failed. */ return false; }