Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * XInclude.java
   *
   * Copyright 2008 Mark Logic Corporation.
   * Portions Copyright 2007 Sun Microsystems, Inc.
   * All rights reserved.
   *
   * The contents of this file are subject to the terms of either the GNU
   * General Public License Version 2 only ("GPL") or the Common
  * Development and Distribution License("CDDL") (collectively, the
  * "License"). You may not use this file except in compliance with the
  * License. You can obtain a copy of the License at
  * https://xproc.dev.java.net/public/CDDL+GPL.html or
  * docs/CDDL+GPL.txt in the distribution. See the License for the
  * specific language governing permissions and limitations under the
  * License. When distributing the software, include this License Header
  * Notice in each file and include the License file at docs/CDDL+GPL.txt.
  */
 
 package com.xmlcalabash.library;
 
 import java.net.URI;
 import java.net.URL;
 
 

Author(s):
ndw
 
 public class XInclude extends DefaultStep implements ProcessMatchingNodes {
     private static final QName xi_include = new QName("http://www.w3.org/2001/XInclude","include");
     private static final QName xi_fallback = new QName("http://www.w3.org/2001/XInclude","fallback");
     private static final QName _fixup_xml_base = new QName("""fixup-xml-base");
     private static final QName _fixup_xml_lang = new QName("""fixup-xml-lang");
     private static final QName cx_mark_roots = new QName("cx",.,"mark-roots");
     private static final QName cx_copy_attributes = new QName("cx",.,"copy-attributes");
     private static final QName cx_root = new QName("cx",.,"root");
     private static final QName _encoding = new QName("""encoding");
     private static final QName _href = new QName("""href");
     private static final QName _parse = new QName("""parse");
     private static final QName _xpointer = new QName("""xpointer");
     private static final Pattern linesXptrRE = Pattern.compile("\\s*lines\\s*\\(\\s*(\\d+)\\s*-\\s*(\\d+)\\s*\\)\\s*");
 
     private ReadablePipe source = null;
     private WritablePipe result = null;
     private Stack<ProcessMatchmatcherStack = new Stack<ProcessMatch> ();
     private Stack<Stringinside = new Stack<String> ();
     private boolean fixupBase = false;
     private boolean fixupLang = false;
     private boolean markRoots = false;
     private boolean copyAttributes = false;
     private Exception mostRecentException = null;

    
Creates a new instance of XInclude
 
     public XInclude(XProcRuntime runtimeXAtomicStep step) {
         super(runtime,step);
     }
 
     public void setInput(String portReadablePipe pipe) {
          = pipe;
     }
 
     public void setOutput(String portWritablePipe pipe) {
          = pipe;
     }
 
     public void reset() {
         .resetReader();
         .resetWriter();
     }
 
     public void run() throws SaxonApiException {
         super.run();
 
          = getOption(false);
          = getOption(false);
        if (mark == null || "false".equals(mark)) {
            // nop
        } else if ("true".equals(mark)) {
             = true;
        } else {
            throw new XProcException("On p:xinclude, cx:copy-attributes must be 'true' or 'false'.");
        }
        mark = getStep().getExtensionAttribute();
        if (mark == null || "false".equals(mark)) {
            // nop
        } else if ("true".equals(mark)) {
             = true;
        } else {
            throw new XProcException("On p:xinclude, cx:mark-roots must be 'true' or 'false'.");
        }
        XdmNode doc = .read();
        XdmNode xdoc = expandXIncludes(doc);
        .write(xdoc);
    }
    private XdmNode expandXIncludes(XdmNode doc) {
        finest(doc"Starting expandXIncludes");
        ProcessMatch matcher = new ProcessMatch(this);
        .push(matcher);
        matcher.match(docnew RuntimeValue("/|*".getNode()));
        XdmNode result = matcher.getResult();
        matcher = .pop();
        return result;
    }
    public boolean processStartDocument(XdmNode nodethrows SaxonApiException {
        //finest(node, "Start document " + matcherStack.size());
        .peek().startDocument(node.getBaseURI());
        return true;
    }
    public void processEndDocument(XdmNode nodethrows SaxonApiException {
        //finest(node, "End document " + matcherStack.size());
        .peek().endDocument();
    }
    public boolean processStartElement(XdmNode nodethrows SaxonApiException {
        //finest(node, "Start element " + node.getNodeName());
        ProcessMatch matcher = .peek();
        if (.equals(node.getNodeName())) {
            String href = node.getAttributeValue();
            String parse = node.getAttributeValue();
            String xptr = node.getAttributeValue();
            XPointer xpointer = null;
            XdmNode subdoc = null;
            if (xptr != null) {
                xpointer = new XPointer(xptr);
            }
            if ("text".equals(parse)) {
                if (!.getAllowXPointerOnText() && xpointer != null) {
                    throw XProcException.stepError(1, "XPointer is not allowed on XInclude when parse='text'");
                }
                String text = readText(hrefnodenode.getBaseURI().toASCIIString(), xpointer);
                if (text == null) {
                    finest(node"XInclude text parse failed: " + href);
                    fallback(nodehref);
                    return false;
                } else {
                    finest(node"XInclude text parse: " + href);
                }
                matcher.addText(text);
                return false;
            } else {
                subdoc = readXML(hrefnode.getBaseURI().toASCIIString());
                String iuri = null;
                if (subdoc == null) {
                    finest(node"XInclude parse failed: " + href);
                    fallback(nodehref);
                    return false;
                } else {
                    iuri = subdoc.getBaseURI().toASCIIString();
                    if (xptr != null) {
                        iuri += "#" + xptr;
                    }
                    if (.contains(iuri)) {
                        throw XProcException.stepError(29,"XInclude document includes itself: " + href);
                    }
                    finest(node"XInclude parse: " + href);
                }
                Vector<XdmNodenodes = null;
                if (xpointer == null) {
                    nodes = new Vector<XdmNode> ();
                    // Put all the children of the document in there, so that we can add xml:base to the root(s)...
                    XdmSequenceIterator iter = subdoc.axisIterator(.);
                    while (iter.hasNext()) {
                        XdmNode child = (XdmNodeiter.next();
                        nodes.add(child);
                    }
                } else {
                    Hashtable<String,StringnsBindings = xpointer.xpathNamespaces();
                    nodes = xpointer.selectNodes(,subdoc);
                }
                for (XdmNode snode : nodes) {
                    if (( ||  ||  || ) && snode.getNodeKind() == .) {
                        Fixup fixup = new Fixup(,node);
                        snode = fixup.fixup(snode);
                    }
                    if (snode.getNodeKind() == . || snode.getNodeKind() == .) {
                        .push(iuri);
                        XdmNode ex = expandXIncludes(snode);
                        matcher.addSubtree(ex);
                        .pop();
                    } else {
                        matcher.addSubtree(snode);
                    }
                }
                return false;
            }
        } else {
            matcher.addStartElement(node);
            matcher.addAttributes(node);
            matcher.startContent();
            return true;
        }
    }
    public void processAttribute(XdmNode nodethrows SaxonApiException {
        throw new UnsupportedOperationException("processAttribute can't happen in XInclude");
    }
    public void processEndElement(XdmNode nodethrows SaxonApiException {
        if (.equals(node.getNodeName())) {
            // Do nothing, we've already output the subtree that replaced xi:include
        } else {
            //finest(node, "End element " + node.getNodeName());
            .peek().addEndElement();
        }
    }
    public void processText(XdmNode nodethrows SaxonApiException {
        throw new UnsupportedOperationException("processText can't happen in XInclude");
    }
    public void processComment(XdmNode nodethrows SaxonApiException {
        throw new UnsupportedOperationException("processComment can't happen in XInclude");
    }
    public void processPI(XdmNode nodethrows SaxonApiException {
        throw new UnsupportedOperationException("processPI can't happen in XInclude");
    }
    public String readText(String hrefXdmNode nodeString baseXPointer xpointer) {
        finest(null"XInclude read text: " + href + " (" + base + ")");
        URI baseURI = null;
        try {
            baseURI = new URI(base);
        } catch (URISyntaxException use) {
            throw new XProcException(use);
        }
        URI hrefURI = baseURI.resolve(href);
        String data = "";
        try {
            URL url = hrefURI.toURL();
            URLConnection conn = url.openConnection();
            String contentType = conn.getContentType();
            int contentLength = conn.getContentLength();
            String charset = HttpUtils.getCharset(contentType);
            if (charset == null && node.getAttributeValue() != null) {
                charset = node.getAttributeValue();
            }
            if (charset == null) {
                charset = "utf-8";
            }
            // Get the response
            InputStreamReader stream = null;
            BufferedReader rd = null;
            if (charset == null) {
                stream = new InputStreamReader(conn.getInputStream());
            } else {
                stream = new InputStreamReader(conn.getInputStream(), charset);
            }
            if (xpointer != null) {
                data = xpointer.selectText(streamcontentLength);
            } else {
                rd = new BufferedReader(stream);
                String line;
                while ((line = rd.readLine()) != null) {
                    data += line + "\n";
                }
                rd.close();
            }
            stream.close();
        } catch (Exception e) {
            finest(null"XInclude read text failed");
             = e;
            return null;
        }
        return data;
    }
    public XdmNode readXML(String hrefString base) {
        finest(null"XInclude read XML: " + href + " (" + base + ")");
        try {
            XdmNode doc = .parse(hrefbase);
            return doc;
        } catch (Exception e) {
            finest(null"XInclude read XML failed");
             = e;
            return null;
        }
    }
    public void fallback(XdmNode nodeString href) {
        finest(node"fallback: " + node.getNodeName());
        boolean valid = true;
        XdmNode fallback = null;
        for (XdmNode child : new RelevantNodes(node.)) {
            if (child.getNodeKind() == .) {
                valid = valid && .equals(child.getNodeName()) && (fallback == null);
                fallback = child;
            } else {
                valid = false;
            }
        }
        if (!valid) {
            throw new XProcException(.getNode(), "XInclude element must contain exactly one xi:fallback element.");
        }
        if (fallback == null) {
            if ( != null) {
                throw new XProcException(.getNode(), "XInclude resource error (" + href + ") and no fallback provided.");
            } else {
                throw new XProcException(.getNode(), "XInclude resource error (" + href + ") and no fallback provided.");
            }
        }
        XdmSequenceIterator iter = fallback.axisIterator(.);
        while (iter.hasNext()) {
            XdmNode fbc = (XdmNodeiter.next();
            if (fbc.getNodeKind() == .) {
                fbc = expandXIncludes(fbc);
            }
            .peek().addSubtree(fbc);
        }
    }
    private class Fixup implements ProcessMatchingNodes {
        private XProcRuntime runtime = null;
        private ProcessMatch matcher = null;
        private boolean root = true;
        private XdmNode xinclude = null;
        public Fixup(XProcRuntime runtimeXdmNode node) {
            this. = runtime;
             = node;
        }
        public XdmNode fixup(XdmNode node) {
             = new ProcessMatch(this);
            .match(nodenew RuntimeValue("*".getNode()));
            XdmNode fixed = .getResult();
            return fixed;
        }
        public boolean processStartDocument(XdmNode nodethrows SaxonApiException {
            .startDocument(node.getBaseURI());
            return true;
        }
        public void processEndDocument(XdmNode nodethrows SaxonApiException {
            .endDocument();
        }
        public boolean processStartElement(XdmNode nodethrows SaxonApiException {
            .addStartElement(node);
            if () {
                 = false;
                if () {
                    XdmSequenceIterator iter = .axisIterator(.);
                    while (iter.hasNext()) {
                        XdmNode child = (XdmNodeiter.next();
                        if (!"".equals(child.getNodeName().getNamespaceURI())) {
                            .addAttribute(child);
                        }
                    }
                }
                XdmSequenceIterator iter = node.axisIterator(.);
                while (iter.hasNext()) {
                    XdmNode child = (XdmNodeiter.next();
                    if ((..equals(child.getNodeName()) && )
                        || (..equals(child.getNodeName()) && )
                        || (.equals(child.getNodeName()) && )) {
                        // nop;
                    } else {
                        .addAttribute(child);
                    }
                }
                if () {
                    .addAttribute(.node.getBaseURI().toASCIIString());
                }
                if () {
                    .addAttribute("true");
                }
                String lang = getLang(node);
                if ( && lang != null) {
                    .addAttribute(.lang);
                }
            } else {
                .addAttributes(node);
            }
            .startContent();
            return true;
        }
        public void processAttribute(XdmNode nodethrows SaxonApiException {
            throw new XProcException(node"This can't happen!?");
        }
        public void processEndElement(XdmNode nodethrows SaxonApiException {
            .addEndElement();
        }
        public void processText(XdmNode nodethrows SaxonApiException {
            throw new XProcException(node"This can't happen!?");
        }
        public void processComment(XdmNode nodethrows SaxonApiException {
            throw new XProcException(node"This can't happen!?");
        }
        public void processPI(XdmNode nodethrows SaxonApiException {
            throw new XProcException(node"This can't happen!?");
        }
        private String getLang(XdmNode node) {
            String lang = null;
            while (lang == null && node.getNodeKind() == .) {
                lang = node.getAttributeValue(.);
                node = node.getParent();
            }
            return lang;
        }
    }
New to GrepCode? Check out our FAQ X