Use stylesheet transformations to output HTML, for example

This commit is contained in:
David Baer
2015-08-11 15:33:08 -04:00
parent cfc0ba7e9a
commit 10927bee25
19 changed files with 725 additions and 92 deletions

119
src/xml.c
View File

@@ -1,46 +1,114 @@
#include <libxml/tree.h>
#include <string.h>
#include "sermon.h"
static xmlNsPtr srmNs = NULL;
static void
appendHeaderNode(xmlNodePtr headerNode, const char* headerName,
const char* headerText) {
appendHeaderNode(xmlNsPtr sermon_ns, xmlNodePtr headerNode,
const char* headerName, const char* headerText) {
if (headerText) {
xmlNodePtr ptr = xmlNewNode(NULL, headerName);
xmlNodePtr ptr = xmlNewNode(sermon_ns, headerName);
xmlAddChild(ptr, xmlNewText(headerText));
xmlAddChild(headerNode, ptr);
}
}
xmlNodePtr
sermonHeader(const Sermon* srm) {
xmlNodePtr header = xmlNewNode(NULL, "header");
appendHeaderNode(header, "title", srm->sermonTitle);
appendHeaderNode(header, "author", srm->sermonAuthor);
appendHeaderNode(header, "occasion", srm->sermonOccasion);
appendHeaderNode(header, "date", srm->sermonDate);
appendHeaderNode(header, "text", srm->sermonText);
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);
appendHeaderNode(sermon_ns, header, "occasion", srm->sermonOccasion);
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_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_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(const SermonParagraph* p) {
xmlNodePtr result = xmlNewNode(NULL, "p");
xmlAddChild(result, xmlNewText(p->paraText));
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(const Sermon* srm) {
xmlNodePtr body = xmlNewNode(NULL, "body");
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(p);
xmlNodePtr para = paragraphToXML(
sermon_ns, p, srm->numReferences, srm->sermonReferences
);
if (p->paraType == PARA_BLOCKQUOTE) {
if (!block) {
block = xmlNewNode(NULL, "quote");
block = xmlNewNode(sermon_ns, "quote");
xmlAddChild(body, block);
}
xmlAddChild(block, para);
@@ -53,16 +121,16 @@ sermonBody(const Sermon* srm) {
}
xmlNodePtr
sermonFooter(const Sermon* srm) {
xmlNodePtr footer = xmlNewNode(NULL, "footer");
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(NULL, "ref");
xmlNodePtr ref = xmlNewNode(sermon_ns, "ref");
snprintf(num, 10, "%d", i + 1);
xmlNewProp(ref, "number", num);
xmlAddChild(ref, paragraphToXML(&r->refText));
xmlAddChild(ref, paragraphToXML(sermon_ns, &r->refText, srm->numReferences, srm->sermonReferences));
xmlAddChild(footer, ref);
}
return footer;
@@ -72,20 +140,21 @@ xmlDocPtr
sermonToXmlDoc(const Sermon* srm) {
/* document creation and setup */
xmlDocPtr document = xmlNewDoc("1.0");
xmlDtdPtr dtd = xmlCreateIntSubset(document, "sermon", NULL, DATADIR "/sermon.dtd");
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(srm));
xmlAddChild(sermon, sermonHeader(sermon_ns, srm));
/* add body paragraphs */
xmlAddChild(sermon, sermonBody(srm));
xmlAddChild(sermon, sermonBody(sermon_ns, srm));
if (srm->numReferences) {
/* add footer */
xmlAddChild(sermon, sermonFooter(srm));
xmlAddChild(sermon, sermonFooter(sermon_ns, srm));
}
return document;