/* * xml.c - Create XML representation of sermon document * Copyright © 2017 David A. Baer * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the organization nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY David A. Baer ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL David A. Baer BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "options.h" #include "sermon.h" static xmlNsPtr srmNs = NULL; static void appendHeaderNode(xmlNsPtr sermon_ns, xmlNodePtr headerNode, const char* headerName, const char* headerText) { if (headerText) { xmlNodePtr ptr = xmlNewNode(sermon_ns, headerName); xmlAddChild(ptr, xmlNewText(headerText)); xmlAddChild(headerNode, ptr); } } xmlNodePtr sermonHeader(xmlNsPtr sermon_ns, const Sermon* srm) { xmlNodePtr header = xmlNewNode(sermon_ns, "header"); appendHeaderNode(sermon_ns, header, "title", srm->sermonTitle); appendHeaderNode(sermon_ns, header, "author", srm->sermonAuthor ? srm->sermonAuthor : options.authorName); appendHeaderNode(sermon_ns, header, "occasion", srm->sermonOccasion); appendHeaderNode(sermon_ns, header, "place", srm->sermonPlace ? srm->sermonPlace : options.placeName); appendHeaderNode(sermon_ns, header, "date", srm->sermonDate); appendHeaderNode(sermon_ns, header, "text", srm->sermonText); return header; } int findReferenceNumber( int numReferences, const SermonReference* sermonReferencesPtr, const char* refId) { int i; for (i = 0; i < numReferences; i++) { if (strcmp(sermonReferencesPtr[i].refId, refId) == 0) { return i + 1; } } return 0; } void formatElementsToXML( xmlNsPtr sermon_ns, xmlNodePtr parentElement, const FormatElement* a, int length, int numReferences, const SermonReference* sermonReferencesPtr) { int i = 0; for (i = 0; i < length; i++) { if (a[i].elementType == FORMAT_EM) { xmlNodePtr em = xmlNewNode(sermon_ns, "em"); formatElementsToXML(sermon_ns, em, a[i].elementContent.nestedContent, a[i].elementContentLength, numReferences, sermonReferencesPtr); xmlAddChild(parentElement, em); } else if (a[i].elementType == FORMAT_BR) { xmlAddChild(parentElement, xmlNewNode(sermon_ns, "br")); } else if (a[i].elementType == FORMAT_TEXT) { xmlAddChild(parentElement, xmlNewText(a[i].elementContent.textContent)); } else if (a[i].elementType == FORMAT_GREEK) { xmlNodePtr greek = xmlNewNode(sermon_ns, "greek"); xmlAddChild(greek, xmlNewText(a[i].elementContent.textContent)); xmlAddChild(parentElement, greek); } else if (a[i].elementType == FORMAT_UNICODE) { xmlNodePtr unicode = xmlNewNode(sermon_ns, "unicode"); xmlAddChild(unicode, xmlNewText(a[i].elementContent.textContent)); xmlAddChild(parentElement, unicode); } else if (a[i].elementType == FORMAT_URL) { xmlNodePtr link = xmlNewNode(sermon_ns, "link"); xmlSetProp(link, "href", a[i].elementContent.textContent); xmlAddChild(link, xmlNewText(a[i].elementContent.textContent)); xmlAddChild(parentElement, link); } else if (a[i].elementType == FORMAT_CITATION) { xmlNodePtr cite = xmlNewNode(sermon_ns, "cite"); int num = findReferenceNumber(numReferences, sermonReferencesPtr, a[i].elementContent.textContent); if (num == 0) { fprintf(stderr, "WARNING: reference %s not found -- omitted\n", a[i].elementContent.textContent); } else { char n[24]; snprintf(n, 24, "%d", num); xmlNewProp(cite, "number", n); xmlAddChild(parentElement, cite); } } } } static xmlNodePtr paragraphToXML( xmlNsPtr sermon_ns, const SermonParagraph* p, int numReferences, const SermonReference* sermonReferencesPtr) { xmlNodePtr result = xmlNewNode(sermon_ns, "p"); formatElementsToXML( sermon_ns, result, p->paraContent, p->paraContentLength, numReferences, sermonReferencesPtr ); return result; } xmlNodePtr sermonBody(xmlNsPtr sermon_ns, const Sermon* srm) { xmlNodePtr body = xmlNewNode(sermon_ns, "body"); xmlNodePtr block = NULL; int i = 0; for (i = 0; i < srm->numParagraphs; i++) { const SermonParagraph* p = &srm->sermonParagraphs[i]; xmlNodePtr para = paragraphToXML( sermon_ns, p, srm->numReferences, srm->sermonReferences ); if (p->paraType == PARA_BLOCKQUOTE) { if (!block) { block = xmlNewNode(sermon_ns, "quote"); xmlAddChild(body, block); } xmlAddChild(block, para); } else { block = NULL; xmlAddChild(body, para); } } return body; } xmlNodePtr sermonFooter(xmlNsPtr sermon_ns, const Sermon* srm) { xmlNodePtr footer = xmlNewNode(sermon_ns, "footer"); int i = 0; char num[10]; for (i = 0; i < srm->numReferences; i++) { const SermonReference* r = &srm->sermonReferences[i]; xmlNodePtr ref = xmlNewNode(sermon_ns, "ref"); snprintf(num, 10, "%d", i + 1); xmlNewProp(ref, "number", num); xmlAddChild(ref, paragraphToXML(sermon_ns, &r->refText, srm->numReferences, srm->sermonReferences)); xmlAddChild(footer, ref); } return footer; } xmlDocPtr sermonToXmlDoc(const Sermon* srm) { /* document creation and setup */ xmlDocPtr document = xmlNewDoc("1.0"); xmlDtdPtr dtd = xmlCreateIntSubset(document, "sermon", NULL, "file://" DATADIR "/sermon.dtd"); xmlNodePtr sermon = xmlNewNode(NULL, "sermon"); xmlNsPtr sermon_ns = xmlNewNs(sermon, "urn:david-sermon", NULL); xmlDocSetRootElement(document, sermon); xmlSetNs(sermon, sermon_ns); /* add header */ xmlAddChild(sermon, sermonHeader(sermon_ns, srm)); /* add body paragraphs */ xmlAddChild(sermon, sermonBody(sermon_ns, srm)); if (srm->numReferences) { /* add footer */ xmlAddChild(sermon, sermonFooter(sermon_ns, srm)); } return document; } void printXML(xmlDocPtr document) { xmlCharEncodingHandlerPtr encoding = xmlFindCharEncodingHandler("utf-8"); xmlOutputBufferPtr output = xmlOutputBufferCreateFd(1, encoding); xmlSaveFileTo(output, document, "utf-8"); }