001    /**
002     * Implements the CFML Function xmlelemnew
003     */
004    package railo.runtime.functions.xml;
005    
006    import org.w3c.dom.Document;
007    import org.w3c.dom.Element;
008    import org.w3c.dom.NamedNodeMap;
009    import org.w3c.dom.Node;
010    
011    import railo.commons.lang.StringUtil;
012    import railo.runtime.PageContext;
013    import railo.runtime.exp.FunctionException;
014    import railo.runtime.ext.function.Function;
015    import railo.runtime.text.xml.XMLUtil;
016    import railo.runtime.text.xml.struct.XMLStructFactory;
017    import railo.runtime.type.util.ListUtil;
018    
019    public final class XmlElemNew implements Function {
020            
021            private static final long serialVersionUID = -2601887739406776466L;
022    
023            public static Element call(PageContext pc , Node node, String childname) throws FunctionException {
024                    return call(pc, node, null, childname);
025            }
026            
027            public static Element call(PageContext pc , Node node, String namespace, String childname) throws FunctionException {
028                    Document doc=XMLUtil.getDocument(node);
029                    
030                    if(StringUtil.isEmpty(childname)) {
031                            if(!StringUtil.isEmpty(namespace)) {
032                                    childname=namespace;
033                                    namespace=null;
034                            }
035                            else throw new FunctionException(pc, "XmlElemNew", 3, "childname", "argument is required");
036                    }
037                    
038                    Element el = null;
039                    
040                    // without namespace
041                    if(StringUtil.isEmpty(namespace)){
042                            if(childname.indexOf(':')!=-1) {
043                                    String[] parts = ListUtil.listToStringArray(childname, ':');
044                                    childname = parts[1];
045                                    String prefix = parts[0];
046                                    namespace = getNamespaceForPrefix(doc.getDocumentElement(),prefix);
047                                    if(StringUtil.isEmpty(namespace)) {
048                                            el=doc.createElement(childname);
049                                    } else {
050                                            el=doc.createElementNS(namespace,childname);
051                                            el.setPrefix(prefix);
052                                    }
053                                    
054                            } else {
055                                    el=doc.createElement(childname);        
056                            }
057                    }
058                    // with namespace
059                    else {
060                            el=doc.createElementNS(namespace, childname);
061                    }
062                    return (Element)XMLStructFactory.newInstance(el,false);
063            }
064            
065            private static String getNamespaceForPrefix(Node node,String prefix) {
066                    if (node==null) return null;
067                    NamedNodeMap atts = node.getAttributes();
068    
069                    if (atts != null) {
070                            String currLocalName,currPrefix;
071                            int len=atts.getLength();
072                            for (int i = 0; i < len; i++) {
073                                    Node currAttr = atts.item(i);
074                                    currLocalName = currAttr.getLocalName();
075                                    currPrefix = currAttr.getPrefix();
076                                    if (prefix.equals(currLocalName) && "xmlns".equals(currPrefix)) {
077                                            return currAttr.getNodeValue();
078                                    } 
079                                    else if (StringUtil.isEmpty(prefix) && "xmlns".equals(currLocalName)
080                                                    && StringUtil.isEmpty(currPrefix)) {
081                                            return currAttr.getNodeValue();
082                                    }
083                            }
084                    }
085                    return null;
086            }
087            
088            
089    }