/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.cocoon.util.jxpath; import org.apache.commons.jxpath.AbstractFactory; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.Pointer; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * A <a href="http://jakarta.apache.org/commons/jxpath">JXPath</a> <code>AbstractFactory</code> * that creates DOM elements. * * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a> * @version $Id$ */ public class DOMFactory extends AbstractFactory { /** * Return <b>false</b> if this factory cannot create the requested object. */ public boolean createObject( JXPathContext context, Pointer pointer, Object parent, String name, int index) { //FIXME: JXPath automatically creates attributes if the element already exists, //but does not call this method if the element does not exit addDOMElement((Node) parent, index, name); return true; } private void addDOMElement(Node parent, int index, String tag) { int pos = tag.indexOf(':'); String prefix = null; if (pos != -1) { prefix = tag.substring(0, pos); } String uri = null; Node child = parent.getFirstChild(); int count = 0; while (child != null) { if (child.getNodeName().equals(tag)) { count++; } child = child.getNextSibling(); } Document doc = parent.getOwnerDocument(); if (doc != null) { uri = getNamespaceURI((Element)parent, prefix); } else { if (parent instanceof Document) { doc = (Document)parent; if (prefix != null) { throw new RuntimeException("Cannot map non-null prefix " + "when creating a document element"); } } else { // Shouldn't happen (must be a DocumentType object) throw new RuntimeException("Node of class " + parent.getClass().getName() + " has null owner document " + "but is not a Document"); } } // Keep inserting new elements until we have index + 1 of them while (count <= index) { Node newElement = doc.createElementNS(uri, tag); parent.appendChild(newElement); count++; } } public String getNamespaceURI(Element element, String prefix) { Node tmp = element; String nsAttr = prefix == null ? "xmlns" : "xmlns:" + prefix; while (tmp != null && tmp.getNodeType() == Node.ELEMENT_NODE) { element = (Element)tmp; // First test element prefixes if (prefix == null) { if (element.getPrefix() == null) { return element.getNamespaceURI(); } } else if(prefix.equals(element.getPrefix())) { return element.getNamespaceURI(); } // Note: stupid DOM api returns "" when an attribute doesn't exist, so we use the Attr node. Attr nsAttrNode = ((Element)tmp).getAttributeNode(nsAttr); if (nsAttrNode != null) { return nsAttrNode.getValue(); } tmp = tmp.getParentNode(); } return null; } public boolean declareVariable(JXPathContext context, String name) { return false; } }