program oldstyle, xmltree, textpatterns; # Note that in March 2010, the and the elements # were removed from the Balisage Conference Paper DTD. This program # has been written to process documents with or without those elements. var sectionNumber : String = "*"; var sectionNumberText : String = "*"; var sectionNumberSuffix : String = ""; var footnoteCount : integer = 0; val patchableStream = new PatchablePrintStream (); val footnotes : PatchablePrintStream = patchableStream.make (); var tocHasBeenEmitted : boolean = false; var tocContents : String = ""; var levelOffset : integer = 1; val stack = new Stack (); stack.push (new Integer (0)); parseXml (); choose xmlElementNode ("article") { patchableStream [":email:"] = ", [NO EMAIL]"; patchableStream [":author:"] = ""; patchableStream [":legal:"] = "

Copyright © 2019 Sam Wilmott

\n"; patchableStream [":keywords:"] = ""; patchableStream [":conf:"] = "

Balisage: The Markup Conference 2019, July 30 - August 2 2019

\n"; patchableStream [":person:"] = ""; with local System.out = patchableStream do { print (""); processChildren; print (footnotes); writePrintMark (":keywords:"); writePrintMark (":author:"); writePrintMark (":person:"); patchableStream [":toc:"] = "

Table Of Contents

\n" "

%s

\n" (tocContents) when tocContents != ""; print ("\n") } patchableStream.emit (); } choose xmlElementNode ("title") when *.parentElement.is ("article") { val titleText : PatchablePrintStream = patchableStream.make (); with local System.out = titleText do processChildren; print ("%s\n" "

%s

\n" (titleText, titleText)); writePrintMark (":author:"); writePrintMark (":conf:"); writePrintMark (":legal:"); print ("

Document processed: %s

\n" (new Date ())); } choose xmlElementNode ("info") { processChildren; } choose xmlElementNode ("abstract") { print ("

Abstract

\n"); processChildren; } choose xmlElementNode ("confgroup") { val confText : PatchablePrintStream = patchableStream.make (); with local System.out = confText do { print ("

"); processChildren; print ("

\n"); } patchableStream [":conf:"] = confText; } choose xmlElementNode ("conftitle") { processChildren; } choose xmlElementNode ("confdates") { print (", "); processChildren; } choose xmlElementNode ("author") { val authorText : PatchablePrintStream = patchableStream.make (); with local System.out = authorText do processChildren; patchableStream [":author:"] = authorText; } choose xmlElementNode ("personname") { print ("

"); processChildren; writePrintMark (":email:"); print ("

\n"); } choose xmlElementNode ("firstname", "surname", "lineage", "othername") { print (" ") when *.hasPrevious; processChildren; } choose xmlElementNode ("personblurb") { val personText : PatchablePrintStream = patchableStream.make (); with local System.out = personText do processChildren; patchableStream [":person:"] = personText; } choose xmlElementNode ("email") { val emailText : PatchablePrintStream = patchableStream.make (); with local System.out = emailText do processChildren; patchableStream [":email:"] = ", %s" (emailText, emailText); } choose xmlElementNode ("legalnotice") { val legalText : PatchablePrintStream = patchableStream.make (); with local System.out = legalText do processChildren; patchableStream [":legal:"] = legalText; } choose xmlElementNode ("keywordset") { val keywordText : PatchablePrintStream = patchableStream.make (); with local System.out = keywordText do { print ("

Keywords: "); processChildren; print ("

\n"); } patchableStream [":keywords:"] = keywordText; } choose xmlElementNode ("keyword") { print (", ") when *.precedingIs ("keyword"); processChildren; } def uAlphaNumber (n : integer) : String :> if n < 0 then "-" + uAlphaNumber (-n) else if n == 0 then "0" else with d : String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" [(n - 1) % 26] :> if n <= 26 then d else uAlphaNumber (n / 26) + d; choose xmlElementNode ("section", "appendix") { if not tocHasBeenEmitted then { tocHasBeenEmitted = true; writePrintMark (":toc:"); } if *.is ("appendix") and *.previousElement..name != "appendix" then { stack.pop (); stack.push (new Integer (1)); } else stack.push (new Integer (stack.pop ().longValue () + 1)); with local sectionNumber = "*" do { if not stack.empty () then { if *.ancestorOrThisIs ("appendix") then sectionNumber = uAlphaNumber(stack.get (0)); else sectionNumber = "%s" (stack.get (0)); for i = 1 to length stack - 1 do sectionNumber += ".%s" (stack.get (i)); if *.ancestorOrThisIs ("appendix") and length stack == 1 then { sectionNumberText = "Appendix %s" (sectionNumber); sectionNumberSuffix = " —"; } else { sectionNumberText = sectionNumber; sectionNumberSuffix = ""; } } stack.push (new Integer (0)); processChildren; stack.pop (); } } choose xmlElementNode ("title") when *.parentElement.is ("section", "appendix") { val sectionDepth : integer = length stack; val titleText : PatchablePrintStream = patchableStream.make (); val sectionLabel : String = sectionNumber.replaceAll ("\\.", "_"); with local System.out = titleText do processChildren; print ("%s%s %s\n" (sectionLabel, sectionDepth, sectionNumberText, sectionNumberSuffix, titleText, sectionDepth)); tocContents += "%s%s%s %s
\n" (sectionDepth * " ", sectionLabel, sectionNumberText, sectionNumberSuffix, titleText); } choose xmlElementNode ("programlisting") { print ("
");
  processChildren;
  print ("
\n"); } choose xmlElementNode ("itemizedlist") { print ("
    "); processChildren; print ("
\n"); } choose xmlElementNode ("listitem") { print ("
  • "); processChildren; print ("
  • \n"); } choose xmlElementNode ("footnote") { footnoteCount += 1; print ("%d" (footnoteCount, footnoteCount)); processChildren; } choose xmlElementNode ("para") when *.parentElement.is ("footnote") { with local System.out = footnotes do { print ("

    Footnotes

    \n") when footnoteCount == 1; print ("

    %d. " (footnoteCount, footnoteCount)); processChildren; print ("

    \n"); } } choose xmlElementNode ("bibliography") { processChildren; } choose xmlElementNode ("title") when *.parentElement.is ("bibliography") { print ("

    "); processChildren; print ("

    \n"); } choose xmlElementNode ("xref") { var linkend : String = null; if * ["linkend"] != null then linkend = "%s" (* ["linkend"].allValues); else System.err.print ("*** Missing xref@linkend attribute!\n"); if linkend != null then { print ("" (linkend)); writePrintMark (":name:" + linkend); print (""); } else print ("MISSING xref@linkend: %s" (*)); } choose xmlElementNode ("bibliomixed") { if * ["xml:id"] != null and * ["xreflabel"] != null then patchableStream [":name:" + * ["xml:id"].allValues] = * ["xreflabel"].allValues else { System.err.print ("*** Missing biblimixed@xml:id attribute!\n") when * ["xml:id"] == null; System.err.print ("*** Missing biblimixed@xreflabel attribute!\n") when * ["xreflabel"] == null; } print ("

    "); print ("" (* ["xml:id"].allValues)) when * ["xml:id"] != null; processChildren; print ("

    \n"); } choose xmlElementNode ("link") { val linkBuffer : PatchablePrintStream = patchableStream.make (); with local System.out = linkBuffer do processChildren; print (": %s" (linkText, linkText)); } } choose xmlElementNode ("para") { print ("

    "); processChildren; print ("

    \n"); } choose xmlElementNode ("emphasis") { var startTag : String = ""; var endTag : String = ""; if * ["role"] != null then select * ["role"].allValues { case "bold": startTag = ""; endTag = ""; case "ital": startTag = ""; endTag = ""; case "bital": startTag = ""; endTag = ""; case "under": startTag = ""; endTag = ""; } else System.err.print ("*** Missing emphasis@role attribute!\n"); print (startTag); processChildren; print (endTag); } choose xmlElementNode { System.err.println ("*** found unmatched %s" (*)); print ("

    <%s>" (*.localName)); processChildren; print ("</%s>

    \n" (*.localName)); } choose xmlTextNode when *.parentElement.is ("article", "info", "confgroup", "author", "personblurb", "legalnotice", "keywordset", "section", "bibliography", "abstract") and not *.isCdata and *.data matches (|- & [" \t\n\r"]* & -|) { } choose xmlTextNode when *.parentElement.is ("programlisting") { selectAll *.data { match (' ' ~ '~' ! ["<>&"] | ["\n\t"])+ => "ok": print (=> "ok"); match /"<": print ("<"); match /">": print (">"); match /"&": print ("&"); match any => "quote": print ("&#%d;" (abs (=> "quote" @ 0))); } } choose xmlTextNode { selectAll *.data { match (' ' ~ '~' | ["\n\t"])+ => "ok": print (=> "ok"); match any => "quote": print ("&#%d;" (abs (=> "quote" @ 0))); } }