blob: 1ec97c0162b1e1719f184fee94f698fa7b9a1eef [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 Chase Technology Ltd - http://www.chasetechnology.co.uk
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Doug Satchwell (Chase Technology Ltd) - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.xsl.core.internal;
import java.util.Stack;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.*;
import org.eclipse.wst.xsl.core.XSLCore;
import org.eclipse.wst.xsl.core.model.*;
import org.w3c.dom.*;
public class StylesheetParser {
private final Stylesheet sf;
private final Stack<Element> elementStack = new Stack<Element>();
private Template currentTemplate;
private Stack<CallTemplate> callTemplates = new Stack<CallTemplate>();
private Stack<Function> functions = new Stack<Function>();
private XSLElement parentEl;
public StylesheetParser(Stylesheet stylesheet) {
this.sf = stylesheet;
}
public void walkDocument(IDOMDocument document) {
if (document.getDocumentElement() != null)
recurse(document.getDocumentElement());
}
private void recurse(Element element) {
XSLElement xslEl = null;
if (XSLCore.XSL_NAMESPACE_URI.equals(element.getNamespaceURI())) {
String elName = element.getLocalName();
if ("stylesheet".equals(elName) && elementStack.size() == 0) //$NON-NLS-1$
{
NamedNodeMap map = element.getAttributes();
String version = element.getAttribute("version"); //$NON-NLS-1$
sf.setVersion(version);
xslEl = sf;
} else if ("include".equals(elName) && elementStack.size() == 1) //$NON-NLS-1$
{
Include include = new Include(sf);
sf.addInclude(include);
xslEl = include;
} else if ("import".equals(elName) && elementStack.size() == 1) //$NON-NLS-1$
{
Import include = new Import(sf);
sf.addImport(include);
xslEl = include;
} else if ("template".equals(elName) && elementStack.size() == 1) //$NON-NLS-1$
{
currentTemplate = new Template(sf);
sf.addTemplate(currentTemplate);
xslEl = currentTemplate;
} else if ("param".equals(elName) && elementStack.size() == 2 && currentTemplate != null) //$NON-NLS-1$
{
Parameter param = new Parameter(sf);
// determine whether param has a value
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (childNode.getNodeType() != Node.ATTRIBUTE_NODE) {
param.setValue(true);
break;
}
}
currentTemplate.addParameter(param);
xslEl = param;
} else if ("call-template".equals(elName) && elementStack.size() >= 2) //$NON-NLS-1$
{
CallTemplate currentCallTemplate = new CallTemplate(sf);
callTemplates.push(currentCallTemplate);
sf.addCalledTemplate(currentCallTemplate);
xslEl = currentCallTemplate;
} else if ("with-param".equals(elName) && elementStack.size() >= 3 && callTemplates.size() > 0) //$NON-NLS-1$
{
Parameter param = new Parameter(sf);
// determine whether param has a value
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (childNode.getNodeType() != Node.ATTRIBUTE_NODE) {
param.setValue(true);
break;
}
}
// get the previous call-template
CallTemplate currentCallTemplate = callTemplates.peek();
currentCallTemplate.addParameter(param);
xslEl = param;
} else if ("variable".equals(elName) || "param".equals(elName)) //$NON-NLS-1$ //$NON-NLS-2$
{
if (elementStack.size() == 1)
{// global variable
Variable var = new Variable(sf);
sf.addGlobalVariable(var);
xslEl = var;
}
else if (elementStack.size() > 1 && currentTemplate != null)
{// local variable
Variable var = new Variable(sf);
currentTemplate.addVariable(var);
xslEl = var;
}
} else if ("function".equals(elName)) { //$NON-NLS-1$
Function function = new Function(sf);
functions.push(function);
sf.addFunction(function);
xslEl = function;
}
else {
xslEl = new XSLElement(sf);
}
if (xslEl!=null)
configure((IDOMNode) element, xslEl);
}
elementStack.push(element);
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
recurse((Element) node);
}
}
if (xslEl instanceof CallTemplate)
callTemplates.pop();
if (xslEl instanceof Function) {
functions.pop();
}
elementStack.pop();
// currentTemplate = null;
// currentCallTemplate = null;
}
private void configure(IDOMNode node, XSLElement element) {
setPositionInfo(node, element);
IDOMElement domElem = (IDOMElement) node;
element.setName(domElem.getLocalName());
NamedNodeMap map = node.getAttributes();
for (int i = 0; i < map.getLength(); i++) {
IDOMAttr attr = (IDOMAttr) map.item(i);
XSLAttribute xslatt = new XSLAttribute(element, attr.getName(),
attr.getValue());
setPositionInfo(attr, xslatt);
element.setAttribute(xslatt);
}
if (parentEl != null)
parentEl.addChild(element);
parentEl = element;
}
private static void setPositionInfo(IDOMNode node, XSLNode inc) {
try {
IStructuredDocument structuredDocument = node
.getStructuredDocument();
int line = structuredDocument.getLineOfOffset(node
.getStartOffset());
int lineOffset = structuredDocument.getLineOffset(line);
int col = node.getStartOffset() - lineOffset;
inc.setOffset(node.getStartOffset());
inc.setLineNumber(line);
inc.setColumnNumber(col);
inc.setLength(node.getLength());
} catch (BadLocationException e) {
XSLCorePlugin.log(e);
}
}
}