com.sun.xml.xsl.XslBuilder Maven / Gradle / Ivy
/*
* @(#)XslBuilder.java 1.7 99/02/05
*
* Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*/
package com.sun.xml.xsl;
import java.io.IOException;
import java.util.Hashtable;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.sun.xml.tree.*;
import com.sun.xml.parser.*;
/**
* This builder is customized to build XSL stylesheets.
*
* @see StyleSheet
*/
public class XslBuilder extends XmlDocumentBuilder
{
private XslBuilder ()
{
setParser (new Parser ());
}
public XmlDocument createDocument ()
{
return new StyleSheet ();
}
/**
* Returns an XSL style sheet parsed from the specified URI,
* which may later be applied to a separate document.
*/
public static StyleSheet createStyleSheet (String documentUri)
throws IOException, SAXException
{
XslBuilder builder = new XslBuilder ();
InputSource input = new InputSource (documentUri);
try {
} catch (Exception e) {
throw new SAXException (e);
}
builder.setDisableNamespaces (false);
builder.setIgnoringLexicalInfo (true);
// XXX XSL "text" should ignore whitespace
builder.getParser ().parse (input);
return builder.getStyleSheet ();
}
/**
* Returns the XML Stylesheet which was produced as a result
* of parsing the document. All imports and inclusions have
* been done, so that the no child of the root element is more
* important than its next sibling.
*
* Note: No protection yet from self-recursiveness;
* that'll just loop forever.
*/
private StyleSheet getStyleSheet ()
throws IOException, SAXException
{
StyleSheet doc = (StyleSheet) getDocument ();
SheetRoot root = (SheetRoot) doc.getDocumentElement ();
ElementNode temp = null;
root.normalize ();
// first do the inclusions ... conceptually, they're imports
// that put nested imports at the end of the current list,
// not the beginning.
for (ElementNode node = (ElementNode) root.getFirstChild ();
node != null;
) {
if (!"include".equals (node.getLocalName ())) {
if ("import".equals (node.getLocalName ()))
temp = node;
node = (ElementNode) node.getNextSibling ();
continue;
}
String uri = node.getAttribute (StyleSheet.uri, "href");
temp = (ElementNode) spliceSheet (node, uri, temp);
ElementNode next = (ElementNode) node.getNextSibling ();
root.removeChild (node);
node = next;
}
// then do the imports ... they're done in groups, with any
// nested imports from one group done as part of the next one
// ("less important").
while ((temp = (ElementNode) root.getFirstChild ()) != null
&& "import".equals (temp.getLocalName ())) {
for (ElementNode node = temp;
node != null && "import".equals (node.getLocalName ());
) {
String uri = node.getAttribute (StyleSheet.uri, "href");
spliceSheet (node, uri, null);
ElementNode next = (ElementNode) node.getNextSibling ();
root.removeChild (node);
node = next;
}
}
return doc;
}
private Node spliceSheet (Node before, String uri, Node lastImport)
throws IOException, SAXException
{
InputSource input = new InputSource (uri);
SheetRoot parent = (SheetRoot) before.getParentNode ();
StyleSheet inclusion, sheet;
SheetRoot root;
getParser ().parse (input);
inclusion = getStyleSheet ();
sheet = (StyleSheet) parent.getOwnerDocument ();
// Now replace "node" with the nodes from the inclusion,
// leaving imports for later
root = (SheetRoot) inclusion.getDocumentElement ();
for (int i = 0; ; i++) {
ElementNode node = (ElementNode) root.item (i);
if (node == null)
break;
if ("import".equals (node.getLocalName ()))
continue;
// move node from imported sheet to this one
sheet.changeNodeOwner (node);
parent.insertBefore (node, before);
// make sure we process the next one.
i--;
}
// Splice the import elements, then -- act on them later.
Node lastBefore;
if (lastImport != null)
lastBefore = lastImport.getNextSibling ();
else
lastBefore = parent.getFirstChild ();
for (int i = 0; ; i++) {
Node node = root.item (i);
if (node == null)
break;
// move import element before first non-import element
sheet.changeNodeOwner (node);
parent.insertBefore (node, lastBefore);
lastImport = node;
i--;
}
return lastImport;
}
}