001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019/**
020 * Implements the CFML Function xmlelemnew
021 */
022package lucee.runtime.functions.xml;
023
024import lucee.commons.lang.StringUtil;
025import lucee.runtime.PageContext;
026import lucee.runtime.exp.FunctionException;
027import lucee.runtime.ext.function.Function;
028import lucee.runtime.text.xml.XMLUtil;
029import lucee.runtime.text.xml.struct.XMLStructFactory;
030import lucee.runtime.type.util.ListUtil;
031
032import org.w3c.dom.Document;
033import org.w3c.dom.Element;
034import org.w3c.dom.NamedNodeMap;
035import org.w3c.dom.Node;
036
037public final class XmlElemNew implements Function {
038        
039        private static final long serialVersionUID = -2601887739406776466L;
040
041        public static Element call(PageContext pc , Node node, String childname) throws FunctionException {
042                return call(pc, node, null, childname);
043        }
044        
045        public static Element call(PageContext pc , Node node, String namespace, String childname) throws FunctionException {
046                Document doc=XMLUtil.getDocument(node);
047                
048                if(StringUtil.isEmpty(childname)) {
049                        if(!StringUtil.isEmpty(namespace)) {
050                                childname=namespace;
051                                namespace=null;
052                        }
053                        else throw new FunctionException(pc, "XmlElemNew", 3, "childname", "argument is required");
054                }
055                
056                Element el = null;
057                
058                // without namespace
059                if(StringUtil.isEmpty(namespace)){
060                        if(childname.indexOf(':')!=-1) {
061                                String[] parts = ListUtil.listToStringArray(childname, ':');
062                                childname = parts[1];
063                                String prefix = parts[0];
064                                namespace = getNamespaceForPrefix(doc.getDocumentElement(),prefix);
065                                if(StringUtil.isEmpty(namespace)) {
066                                        el=doc.createElement(childname);
067                                } else {
068                                        el=doc.createElementNS(namespace,childname);
069                                        el.setPrefix(prefix);
070                                }
071                                
072                        } else {
073                                el=doc.createElement(childname);        
074                        }
075                }
076                // with namespace
077                else {
078                        el=doc.createElementNS(namespace, childname);
079                }
080                return (Element)XMLStructFactory.newInstance(el,false);
081        }
082        
083        private static String getNamespaceForPrefix(Node node,String prefix) {
084                if (node==null) return null;
085                NamedNodeMap atts = node.getAttributes();
086
087                if (atts != null) {
088                        String currLocalName,currPrefix;
089                        int len=atts.getLength();
090                        for (int i = 0; i < len; i++) {
091                                Node currAttr = atts.item(i);
092                                currLocalName = currAttr.getLocalName();
093                                currPrefix = currAttr.getPrefix();
094                                if (prefix.equals(currLocalName) && "xmlns".equals(currPrefix)) {
095                                        return currAttr.getNodeValue();
096                                } 
097                                else if (StringUtil.isEmpty(prefix) && "xmlns".equals(currLocalName)
098                                                && StringUtil.isEmpty(currPrefix)) {
099                                        return currAttr.getNodeValue();
100                                }
101                        }
102                }
103                return null;
104        }
105        
106        
107}