Package dk.brics.xact.operations

Source Code of dk.brics.xact.operations.ParseHandler

package dk.brics.xact.operations;

import java.util.LinkedList;
import java.util.Stack;

import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.DefaultHandler2;

import dk.brics.misc.Origin;
import dk.brics.xact.AttrNode;
import dk.brics.xact.Attribute;
import dk.brics.xact.AttributeGap;
import dk.brics.xact.Comment;
import dk.brics.xact.Element;
import dk.brics.xact.NamespaceDecl;
import dk.brics.xact.Node;
import dk.brics.xact.ProcessingInstruction;
import dk.brics.xact.TempNode;
import dk.brics.xact.TemplateGap;
import dk.brics.xact.Text;
import dk.brics.xact.XML;

/**
* A SAX parser that given a stream SAX events generates an XACT document
*/
public class ParseHandler extends DefaultHandler2 {

    private final Stack<Stack<Node>> siblings = new Stack<Stack<Node>>();

    private XML root;

    private Locator locator;

    private final Origin base;

    private LinkedList<NamespaceDecl> nsDecls = new LinkedList<NamespaceDecl>();

    /**
     * Constructs a new parse handler.
     */
    public ParseHandler(Origin base) {
        this.base = base;
    }
   
    /**
     * Returns the resulting XML template.
     */
    public XML getRoot() {
      return root;
    }

    @Override
    public void setDocumentLocator(Locator locator) {
        this.locator = locator;
    }

    private Attribute makeAttributes(Attributes as, Origin origin) {
        Attribute a = null;
        for (int i = 0; i < as.getLength(); i++) {
            String ns = as.getURI(i);
            if (ns.length() == 0) {
                ns = null;
            }
            if ((ns == null || ns.equals("http://www.w3.org/2000/xmlns/")) && as.getLocalName(i).equals("xmlns")) { // TODO: Why do we need to filter these in the results from XSL transformation? startPrefixMapping is called correctly
                continue;
            }
            a = new Attribute(ns, as.getLocalName(i), as.getValue(i), a, origin);
        }
        return a;
    }

    private Origin getOrigin() { // TODO: improve origin tracking (messed up by wrapAndConvertGaps)
        Origin origin = null;
        if (base != null) {
            int line = base.getLine();
            int col = base.getColumn();
            if (locator.getLineNumber() == 1) {
                col += locator.getColumnNumber();
            } else {
                line += locator.getLineNumber();
                col = locator.getColumnNumber();
            }
            origin = new Origin(base.getFile(), line, col);
        }
        return origin;
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws SAXException {
      if (!uri.equals(XMLParser.XACT_NAMESPACE)) {
        NamespaceDecl newNs = new NamespaceDecl(prefix, uri);
        nsDecls.addFirst(newNs); // the list will now holds the declarations in reverse order
      }
    }

    @Override
    public void startDocument() {
        siblings.push(new Stack<Node>());
    }

    @Override
    public void endDocument() {
        Stack<Node> stack = siblings.peek();
        if (stack.peek() instanceof Element)
            root = (Element) stack.peek(); // TODO: ignores PI/comments before/after root element!!!
        else {
            root = XML.concat(stack);
        }
    }

    @Override
    public void startElement(String uri, String localname, String name, Attributes attrs) {
        Origin origin = getOrigin();
        Node n;
        if (uri.equals(XMLParser.XACT_NAMESPACE)) {
            if (localname.equals("tgap")) {
                n = new TemplateGap(attrs.getValue("", "gap"), attrs.getValue("", "type"), origin);
            } else { // agap
                String ns = null;
                String aname = null;
                String gap = null;
                for (int i = 0; i < attrs.getLength(); i++) {
                    aname = attrs.getLocalName(i);
                    if (!attrs.getURI(i).equals(XMLParser.XACT_NAMESPACE)) {
                        ns = attrs.getURI(i);
                        if (ns.length() == 0) {
                            ns = null;
                        }
                        gap = attrs.getValue(i);
                        break;
                    }
                }
                String type = attrs.getValue(XMLParser.XACT_NAMESPACE, "type");
                n = new AttributeGap(ns, aname, gap, type, origin);
            }
        } else {
            NamespaceDecl lns = null;
            for (NamespaceDecl ns : nsDecls) {
                lns = new NamespaceDecl(ns.getPrefix(), ns.getNamespace(),lns, null);
            }
            n = new Element(uri, localname, makeAttributes(attrs, origin), null, lns, null, origin);
            nsDecls = new LinkedList<NamespaceDecl>();
        }
        siblings.peek().push(n);
        siblings.push(new Stack<Node>());
    }

    @Override
    public void endElement(String uri, String localname, String name) {
        Stack<Node> children = siblings.pop();
        TempNode c = null;
        Node n = siblings.peek().pop();
        if (n instanceof Element) {
            Element e = (Element) n;
            AttrNode a = e.getFirstAttr();
            while (!children.isEmpty()) {
                Node m = children.pop();
                if (m instanceof AttributeGap) { // element with agap child
                    a = ((AttributeGap) m).copy(a);
                } else {
                    c = ((TempNode) m).copy(c);
                }
            }
            n = e.copy(a, c, e.getNextSibling());
        } else if (n instanceof AttributeGap) {
            if (!siblings.peek().isEmpty()) {
                Node m = siblings.peek().pop();
                if (m instanceof Element) { // element with agap successor
                    Element f = (Element) m;
                    m = f.copy(((AttributeGap) n).copy(f.getFirstAttr()), f.getFirstChild(), f.getNextSibling());
                    n = null;
                }
                siblings.peek().push(m);
            }
        }
        if (n != null) {
            siblings.peek().push(n);
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) {
        siblings.peek().push(new Text(new String(ch, start, length), getOrigin()));
    }

    @Override
    public void processingInstruction(String target, String data) {
        siblings.peek().push(new ProcessingInstruction(target, data, getOrigin()));
    }

    @Override
    public void comment(char[] ch, int start, int length) {
        siblings.peek().push(new Comment(new String(ch, start, length), getOrigin()));
    }
}
TOP

Related Classes of dk.brics.xact.operations.ParseHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.