1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id: SerializerUtils.java 468642 2006-10-28 06:55:10Z minchau $ 20 */ 21 package org.apache.xalan.serialize; 22 23 import javax.xml.transform.TransformerException; 24 25 import org.apache.xalan.transformer.TransformerImpl; 26 import org.apache.xml.dtm.DTM; 27 import org.apache.xml.serializer.NamespaceMappings; 28 import org.apache.xml.serializer.SerializationHandler; 29 import org.apache.xpath.XPathContext; 30 import org.apache.xpath.objects.XObject; 31 import org.xml.sax.SAXException; 32 33 /** 34 * Class that contains only static methods that are used to "serialize", 35 * these methods are used by Xalan and are not in org.apache.xml.serializer 36 * because they have dependancies on the packages org.apache.xpath or org. 37 * apache.xml.dtm or org.apache.xalan.transformer. The package org.apache.xml. 38 * serializer should not depend on Xalan or XSLTC. 39 * @xsl.usage internal 40 */ 41 public class SerializerUtils 42 { 43 44 /** 45 * Copy an DOM attribute to the created output element, executing 46 * attribute templates as need be, and processing the xsl:use 47 * attribute. 48 * 49 * @param handler SerializationHandler to which the attributes are added. 50 * @param attr Attribute node to add to SerializationHandler. 51 * 52 * @throws TransformerException 53 */ addAttribute(SerializationHandler handler, int attr)54 public static void addAttribute(SerializationHandler handler, int attr) 55 throws TransformerException 56 { 57 58 TransformerImpl transformer = 59 (TransformerImpl) handler.getTransformer(); 60 DTM dtm = transformer.getXPathContext().getDTM(attr); 61 62 if (SerializerUtils.isDefinedNSDecl(handler, attr, dtm)) 63 return; 64 65 String ns = dtm.getNamespaceURI(attr); 66 67 if (ns == null) 68 ns = ""; 69 70 // %OPT% ...can I just store the node handle? 71 try 72 { 73 handler.addAttribute( 74 ns, 75 dtm.getLocalName(attr), 76 dtm.getNodeName(attr), 77 "CDATA", 78 dtm.getNodeValue(attr), false); 79 } 80 catch (SAXException e) 81 { 82 // do something? 83 } 84 } // end copyAttributeToTarget method 85 86 /** 87 * Copy DOM attributes to the result element. 88 * 89 * @param src Source node with the attributes 90 * 91 * @throws TransformerException 92 */ addAttributes(SerializationHandler handler, int src)93 public static void addAttributes(SerializationHandler handler, int src) 94 throws TransformerException 95 { 96 97 TransformerImpl transformer = 98 (TransformerImpl) handler.getTransformer(); 99 DTM dtm = transformer.getXPathContext().getDTM(src); 100 101 for (int node = dtm.getFirstAttribute(src); 102 DTM.NULL != node; 103 node = dtm.getNextAttribute(node)) 104 { 105 addAttribute(handler, node); 106 } 107 } 108 109 /** 110 * Given a result tree fragment, walk the tree and 111 * output it to the SerializationHandler. 112 * 113 * @param obj Result tree fragment object 114 * @param support XPath context for the result tree fragment 115 * 116 * @throws org.xml.sax.SAXException 117 */ outputResultTreeFragment( SerializationHandler handler, XObject obj, XPathContext support)118 public static void outputResultTreeFragment( 119 SerializationHandler handler, 120 XObject obj, 121 XPathContext support) 122 throws org.xml.sax.SAXException 123 { 124 125 int doc = obj.rtf(); 126 DTM dtm = support.getDTM(doc); 127 128 if (null != dtm) 129 { 130 for (int n = dtm.getFirstChild(doc); 131 DTM.NULL != n; 132 n = dtm.getNextSibling(n)) 133 { 134 handler.flushPending(); 135 136 // I think. . . . This used to have a (true) arg 137 // to flush prefixes, will that cause problems ??? 138 if (dtm.getNodeType(n) == DTM.ELEMENT_NODE 139 && dtm.getNamespaceURI(n) == null) 140 handler.startPrefixMapping("", ""); 141 dtm.dispatchToEvents(n, handler); 142 } 143 } 144 } 145 146 /** 147 * Copy <KBD>xmlns:</KBD> attributes in if not already in scope. 148 * 149 * As a quick hack to support ClonerToResultTree, this can also be used 150 * to copy an individual namespace node. 151 * 152 * @param src Source Node 153 * NEEDSDOC @param type 154 * NEEDSDOC @param dtm 155 * 156 * @throws TransformerException 157 */ processNSDecls( SerializationHandler handler, int src, int type, DTM dtm)158 public static void processNSDecls( 159 SerializationHandler handler, 160 int src, 161 int type, 162 DTM dtm) 163 throws TransformerException 164 { 165 166 try 167 { 168 if (type == DTM.ELEMENT_NODE) 169 { 170 for (int namespace = dtm.getFirstNamespaceNode(src, true); 171 DTM.NULL != namespace; 172 namespace = dtm.getNextNamespaceNode(src, namespace, true)) 173 { 174 175 // String prefix = dtm.getPrefix(namespace); 176 String prefix = dtm.getNodeNameX(namespace); 177 String desturi = handler.getNamespaceURIFromPrefix(prefix); 178 // String desturi = getURI(prefix); 179 String srcURI = dtm.getNodeValue(namespace); 180 181 if (!srcURI.equalsIgnoreCase(desturi)) 182 { 183 handler.startPrefixMapping(prefix, srcURI, false); 184 } 185 } 186 } 187 else if (type == DTM.NAMESPACE_NODE) 188 { 189 String prefix = dtm.getNodeNameX(src); 190 // Brian M. - some changes here to get desturi 191 String desturi = handler.getNamespaceURIFromPrefix(prefix); 192 String srcURI = dtm.getNodeValue(src); 193 194 if (!srcURI.equalsIgnoreCase(desturi)) 195 { 196 handler.startPrefixMapping(prefix, srcURI, false); 197 } 198 } 199 } 200 catch (org.xml.sax.SAXException se) 201 { 202 throw new TransformerException(se); 203 } 204 } 205 206 /** 207 * Returns whether a namespace is defined 208 * 209 * 210 * @param attr Namespace attribute node 211 * @param dtm The DTM that owns attr. 212 * 213 * @return True if the namespace is already defined in 214 * list of namespaces 215 */ isDefinedNSDecl( SerializationHandler serializer, int attr, DTM dtm)216 public static boolean isDefinedNSDecl( 217 SerializationHandler serializer, 218 int attr, 219 DTM dtm) 220 { 221 222 if (DTM.NAMESPACE_NODE == dtm.getNodeType(attr)) 223 { 224 225 // String prefix = dtm.getPrefix(attr); 226 String prefix = dtm.getNodeNameX(attr); 227 String uri = serializer.getNamespaceURIFromPrefix(prefix); 228 // String uri = getURI(prefix); 229 230 if ((null != uri) && uri.equals(dtm.getStringValue(attr))) 231 return true; 232 } 233 234 return false; 235 } 236 237 /** 238 * This function checks to make sure a given prefix is really 239 * declared. It might not be, because it may be an excluded prefix. 240 * If it's not, it still needs to be declared at this point. 241 * TODO: This needs to be done at an earlier stage in the game... -sb 242 * 243 * NEEDSDOC @param dtm 244 * NEEDSDOC @param namespace 245 * 246 * @throws org.xml.sax.SAXException 247 */ ensureNamespaceDeclDeclared( SerializationHandler handler, DTM dtm, int namespace)248 public static void ensureNamespaceDeclDeclared( 249 SerializationHandler handler, 250 DTM dtm, 251 int namespace) 252 throws org.xml.sax.SAXException 253 { 254 255 String uri = dtm.getNodeValue(namespace); 256 String prefix = dtm.getNodeNameX(namespace); 257 258 if ((uri != null && uri.length() > 0) && (null != prefix)) 259 { 260 String foundURI; 261 NamespaceMappings ns = handler.getNamespaceMappings(); 262 if (ns != null) 263 { 264 265 foundURI = ns.lookupNamespace(prefix); 266 if ((null == foundURI) || !foundURI.equals(uri)) 267 { 268 handler.startPrefixMapping(prefix, uri, false); 269 } 270 } 271 } 272 } 273 } 274