--- /dev/null
+// Text - Saxon extension element for inserting text
+
+package com.nwalsh.saxon8;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.net.URL;
+import java.net.MalformedURLException;
+
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.URIResolver;
+import javax.xml.transform.Source;
+
+import net.sf.saxon.Controller;
+import net.sf.saxon.instruct.ExtensionInstruction;
+import net.sf.saxon.event.Receiver;
+import net.sf.saxon.expr.Expression;
+import net.sf.saxon.instruct.Executable;
+import net.sf.saxon.expr.SimpleExpression;
+import net.sf.saxon.expr.XPathContext;
+import net.sf.saxon.om.Item;
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.om.NamePool;
+import net.sf.saxon.xpath.XPathException;
+
+/*
+import net.sf.saxon.value.AtomicValue;
+import net.sf.saxon.value.ObjectValue;
+*/
+
+import org.xml.sax.AttributeList;
+
+/**
+ * <p>Saxon extension element for inserting text
+ *
+ * <p>$Id$</p>
+ *
+ * <p>Copyright (C) 2000 Norman Walsh.</p>
+ *
+ * <p>This class provides a
+ * <a href="http://users.iclway.co.uk/mhkay/saxon/">Saxon</a>
+ * extension element for inserting text into a result tree.</p>
+ *
+ * <p><b>Change Log:</b></p>
+ * <dl>
+ * <dt>1.0</dt>
+ * <dd><p>Initial release.</p></dd>
+ * </dl>
+ *
+ * @author Norman Walsh
+ * <a href="mailto:ndw@nwalsh.com">ndw@nwalsh.com</a>
+ *
+ * @version $Id$
+ *
+ */
+public class Text extends ExtensionInstruction {
+ Expression hrefExpr;
+ Expression encodingExpr;
+
+ /**
+ * <p>Constructor for Text</p>
+ *
+ * <p>Does nothing.</p>
+ */
+ public Text() {
+ }
+
+ /**
+ * <p>Can this element contain a template-body?</p>
+ *
+ * <p>Yes, it can, but only so that it can contain xsl:fallback.</p>
+ *
+ * @return true
+ */
+ public boolean mayContainTemplateBody() {
+ return true;
+ }
+
+ /**
+ * <p>Validate the arguments</p>
+ *
+ * <p>The element must have an href attribute.</p>
+ */
+ public void prepareAttributes() throws TransformerConfigurationException {
+ // Get mandatory href attribute
+ String fnAtt = getAttribute("href");
+ if (fnAtt == null || "".equals(fnAtt)) {
+ reportAbsence("href");
+ }
+ hrefExpr = makeAttributeValueTemplate(fnAtt);
+
+ fnAtt = getAttribute("encoding");
+ if (fnAtt == null || "".equals(fnAtt)) {
+ encodingExpr = null;
+ } else {
+ encodingExpr = makeAttributeValueTemplate(fnAtt);
+ }
+ }
+
+ /** Validate that the element occurs in a reasonable place. */
+ public void validate() throws TransformerConfigurationException {
+ checkWithinTemplate();
+ hrefExpr = typeCheck("href", hrefExpr);
+ if (encodingExpr != null) {
+ encodingExpr = typeCheck("encoding", encodingExpr);
+ }
+ }
+
+ public Expression compile(Executable exec)
+ throws TransformerConfigurationException {
+ return new TextInstruction(hrefExpr, encodingExpr);
+ }
+
+ private static class TextInstruction extends SimpleExpression {
+ Expression hrefExpr;
+ Expression encodingExpr;
+
+ public TextInstruction(Expression hrefExpr, Expression encExpr) {
+ this.hrefExpr = hrefExpr;
+ encodingExpr = encExpr;
+ }
+
+ public int getImplementationMethod() {
+ return EVALUATE_METHOD;
+ }
+
+ public String getExpressionType() {
+ return "s8text:insertfile";
+ }
+
+ /**
+ * <p>Insert the text of the file into the result tree</p>
+ *
+ * <p>Processing this element inserts the contents of the URL named
+ * by the href attribute into the result tree as plain text.</p>
+ *
+ * <p>Optional encoding attribute can specify encoding of resource.
+ * If not specified default system encoding is used.</p>
+ *
+ */
+ public Item evaluateItem(XPathContext context) throws XPathException {
+ Controller controller = context.getController();
+ NamePool namePool = controller.getNamePool();
+ Receiver out = context.getReceiver();
+ String href = hrefExpr.evaluateAsString(context);
+
+ String encoding = "";
+ if (encodingExpr != null) {
+ encoding = encodingExpr.evaluateAsString(context);
+ }
+
+ String baseURI = ((NodeInfo) context.getContextItem()).getBaseURI();
+
+ URIResolver resolver = context.getController().getURIResolver();
+
+ if (resolver != null) {
+ try {
+ Source source = resolver.resolve(href, baseURI);
+ href = source.getSystemId();
+ } catch (TransformerException te) {
+ // nop
+ }
+ }
+
+ URL baseURL = null;
+ URL fileURL = null;
+
+ try {
+ baseURL = new URL(baseURI);
+ } catch (MalformedURLException e0) {
+ // what the!?
+ baseURL = null;
+ }
+
+ try {
+ try {
+ fileURL = new URL(baseURL, href);
+ } catch (MalformedURLException e1) {
+ try {
+ fileURL = new URL(baseURL, "file:" + href);
+ } catch (MalformedURLException e2) {
+ System.out.println("Cannot open " + href);
+ return null;
+ }
+ }
+
+ InputStreamReader isr = null;
+ if (encoding.equals("") == true)
+ isr = new InputStreamReader(fileURL.openStream());
+ else
+ isr = new InputStreamReader(fileURL.openStream(), encoding);
+
+ BufferedReader is = new BufferedReader(isr);
+
+ final int BUFFER_SIZE = 4096;
+ char chars[] = new char[BUFFER_SIZE];
+ char nchars[] = new char[BUFFER_SIZE];
+ int len = 0;
+ int i = 0;
+ int carry = -1;
+
+ while ((len = is.read(chars)) > 0) {
+ // various new lines are normalized to LF to prevent blank lines
+ // between lines
+
+ int nlen = 0;
+ for (i=0; i<len; i++) {
+ // is current char CR?
+ if (chars[i] == '\r') {
+ if (i < (len - 1)) {
+ // skip it if next char is LF
+ if (chars[i+1] == '\n') continue;
+ // single CR -> LF to normalize MAC line endings
+ nchars[nlen] = '\n';
+ nlen++;
+ continue;
+ } else {
+ // if CR is last char of buffer we must look ahead
+ carry = is.read();
+ nchars[nlen] = '\n';
+ nlen++;
+ if (carry == '\n') {
+ carry = -1;
+ }
+ break;
+ }
+ }
+ nchars[nlen] = chars[i];
+ nlen++;
+ }
+
+ out.characters(String.valueOf(nchars), 0, 0);
+ // handle look aheaded character
+ if (carry != -1) out.characters(String.valueOf((char)carry), 0, 0);
+ carry = -1;
+ }
+ is.close();
+ } catch (Exception e) {
+ System.out.println("Cannot read " + href);
+ }
+
+ return null;
+ }
+ }
+}
tree.setConfiguration(config);
builder.setConfiguration(config);
- tree.startDocument();
+ tree.open();
+ tree.startDocument(0);
wrapper = findWrapper(wrapperns);
}
tree.endDocument();
+ tree.close();
return builder.getCurrentDocument();
}
// Maybe node is an element, a text node, a comment, or a PI
switch (node.getNodeKind()) {
case Type.ELEMENT:
- tree.startElement(node.getNameCode(), 0, 0);
+ tree.startElement(node.getNameCode(), 0, 0, 0);
{
AxisIterator attrIter = node.iterateAxis(Axis.ATTRIBUTE);
NodeInfo attr = (NodeInfo) attrIter.next();
while (attr != null) {
- tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0);
+ tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0, 0);
attr = (NodeInfo) attrIter.next();
}
}
String text = node.getStringValue();
int pos = text.indexOf('\n');
while (pos >= 0) {
- tree.characters(text.substring(0, pos), 0);
+ tree.characters(text.substring(0, pos), 0, 0);
// Close any open elements
for (int openpos = 0; openpos < openElements.size(); openpos++) {
}
// Output the line number
- tree.characters("\n", 0);
+ tree.characters("\n", 0, 0);
lineNumber++;
formatLineNumber(pool, tree);
for (int openpos = 0; openpos < openElements.size(); openpos++) {
NodeInfo onode = (NodeInfo) openElements.get(openpos);
- tree.startElement(onode.getNameCode(), 0, 0);
+ tree.startElement(onode.getNameCode(), 0, 0, 0);
AxisIterator oattrIter = onode.iterateAxis(Axis.ATTRIBUTE);
NodeInfo attr = (NodeInfo) oattrIter.next();
while (attr != null) {
// Don't output {xml:}id attributes again
if (!"id".equals(attr.getLocalPart())) {
- tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0);
+ tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0, 0);
}
attr = (NodeInfo) oattrIter.next();
}
text = text.substring(pos+1);
pos = text.indexOf('\n');
}
- tree.characters(text, 0);
+ tree.characters(text, 0, 0);
break;
case Type.COMMENT:
- tree.comment(node.getStringValue(), 0);
+ tree.comment(node.getStringValue(), 0, 0);
break;
case Type.PROCESSING_INSTRUCTION:
tree.processingInstruction(node.getDisplayName(),
- node.getStringValue(), 0);
+ node.getStringValue(), 0, 0);
break;
default:
System.err.println("Error!");
lno += separator;
if (wrapper != null) {
- tree.startElement(wrapper.getNameCode(), 0, 0);
+ tree.startElement(wrapper.getNameCode(), 0, 0, 0);
AxisIterator attrIter = wrapper.iterateAxis(Axis.ATTRIBUTE);
NodeInfo attr = (NodeInfo) attrIter.next();
while (attr != null) {
- tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0);
+ tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0, 0);
attr = (NodeInfo) attrIter.next();
}
tree.startContent();
}
- tree.characters(lno, 0);
+ tree.characters(lno, 0, 0);
if (wrapper != null) {
tree.endElement();
tree.setConfiguration(config);
builder.setConfiguration(config);
- tree.startDocument();
+ tree.open();
+ tree.startDocument(0);
// Start at (1,1)
lineNumber = 1;
}
tree.endDocument();
+ tree.close();
return builder.getCurrentDocument();
}
// Maybe node is an element, a text node, a comment, or a PI
switch (node.getNodeKind()) {
case Type.ELEMENT:
- tree.startElement(node.getNameCode(), 0, 0);
+ tree.startElement(node.getNameCode(), 0, 0, 0);
{
AxisIterator attrIter = node.iterateAxis(Axis.ATTRIBUTE);
NodeInfo attr = (NodeInfo) attrIter.next();
while (attr != null) {
- tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0);
+ tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0, 0);
attr = (NodeInfo) attrIter.next();
}
}
while (callout != null && "\n".equals(ch)
&& lineNumber == callout.getLine()) {
- tree.characters(" ", 0);
+ tree.characters(" ", 0, 0);
colNumber++;
done = false;
}
}
- tree.characters(ch, 0);
+ tree.characters(ch, 0, 0);
if ("\n".equals(ch)) {
lineNumber++;
}
}
} else {
- tree.characters(text, 0);
+ tree.characters(text, 0, 0);
}
break;
case Type.COMMENT:
- tree.comment(node.getStringValue(), 0);
+ tree.comment(node.getStringValue(), 0, 0);
break;
case Type.PROCESSING_INSTRUCTION:
tree.processingInstruction(node.getDisplayName(),
- node.getStringValue(), 0);
+ node.getStringValue(), 0, 0);
break;
default:
System.err.println("Error!");
switch (style) {
case CALLOUT_TEXT:
startCalloutWrapper(callout, textWrapper, tree);
- tree.characters(textPrefix + callout.getCallout() + textSuffix, 0);
+ tree.characters(textPrefix + callout.getCallout() + textSuffix, 0, 0);
endCalloutWrapper(textWrapper, tree);
break;
case CALLOUT_UNICODE:
char chars[] = new char[1];
chars[0] = (char) codepoint;
String unicodeCh = new String(chars);
- tree.characters(unicodeCh, 0);
+ tree.characters(unicodeCh, 0, 0);
endCalloutWrapper(unicodeWrapper, tree);
break;
case CALLOUT_GRAPHICS:
for (int openpos = 0; openpos < openElements.size(); openpos++) {
NodeInfo onode = (NodeInfo) openElements.get(openpos);
- tree.startElement(onode.getNameCode(), 0, 0);
+ tree.startElement(onode.getNameCode(), 0, 0, 0);
AxisIterator oattrIter = onode.iterateAxis(Axis.ATTRIBUTE);
NodeInfo attr = (NodeInfo) oattrIter.next();
while (attr != null) {
// Don't output {xml:}id attributes again
if (!"id".equals(attr.getLocalPart())) {
- tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0);
+ tree.attribute(attr.getNameCode(), 0, attr.getStringValue(), 0, 0);
}
attr = (NodeInfo) oattrIter.next();
}
Receiver tree)
throws TransformerException {
if (wrapper != null) {
- tree.startElement(wrapper.getNameCode(), 0, 0);
+ tree.startElement(wrapper.getNameCode(), 0, 0, 0);
AxisIterator attrIter = wrapper.iterateAxis(Axis.ATTRIBUTE);
NodeInfo attr = (NodeInfo) attrIter.next();
while (attr != null) {
String value = attr.getStringValue().replaceAll("\\{CALLOUT\\}",
""+callout.getCallout());
- tree.attribute(attr.getNameCode(), 0, value, 0);
+ tree.attribute(attr.getNameCode(), 0, value, 0, 0);
attr = (NodeInfo) attrIter.next();
}
tree.startContent();