001: /*
002: * Copyright 1999-2005 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: SerializerUtils.java,v 1.6 2005/02/11 06:18:14 minchau Exp $
018: */
019: package org.apache.xalan.serialize;
020:
021: import javax.xml.transform.TransformerException;
022:
023: import org.apache.xalan.transformer.TransformerImpl;
024: import org.apache.xml.dtm.DTM;
025: import org.apache.xml.serializer.NamespaceMappings;
026: import org.apache.xml.serializer.SerializationHandler;
027: import org.apache.xpath.XPathContext;
028: import org.apache.xpath.objects.XObject;
029: import org.xml.sax.SAXException;
030:
031: /**
032: * Class that contains only static methods that are used to "serialize",
033: * these methods are used by Xalan and are not in org.apache.xml.serializer
034: * because they have dependancies on the packages org.apache.xpath or org.
035: * apache.xml.dtm or org.apache.xalan.transformer. The package org.apache.xml.
036: * serializer should not depend on Xalan or XSLTC.
037: * @xsl.usage internal
038: */
039: public class SerializerUtils {
040:
041: /**
042: * Copy an DOM attribute to the created output element, executing
043: * attribute templates as need be, and processing the xsl:use
044: * attribute.
045: *
046: * @param handler SerializationHandler to which the attributes are added.
047: * @param attr Attribute node to add to SerializationHandler.
048: *
049: * @throws TransformerException
050: */
051: public static void addAttribute(SerializationHandler handler,
052: int attr) throws TransformerException {
053:
054: TransformerImpl transformer = (TransformerImpl) handler
055: .getTransformer();
056: DTM dtm = transformer.getXPathContext().getDTM(attr);
057:
058: if (SerializerUtils.isDefinedNSDecl(handler, attr, dtm))
059: return;
060:
061: String ns = dtm.getNamespaceURI(attr);
062:
063: if (ns == null)
064: ns = "";
065:
066: // %OPT% ...can I just store the node handle?
067: try {
068: handler.addAttribute(ns, dtm.getLocalName(attr), dtm
069: .getNodeName(attr), "CDATA",
070: dtm.getNodeValue(attr), false);
071: } catch (SAXException e) {
072: // do something?
073: }
074: } // end copyAttributeToTarget method
075:
076: /**
077: * Copy DOM attributes to the result element.
078: *
079: * @param src Source node with the attributes
080: *
081: * @throws TransformerException
082: */
083: public static void addAttributes(SerializationHandler handler,
084: int src) throws TransformerException {
085:
086: TransformerImpl transformer = (TransformerImpl) handler
087: .getTransformer();
088: DTM dtm = transformer.getXPathContext().getDTM(src);
089:
090: for (int node = dtm.getFirstAttribute(src); DTM.NULL != node; node = dtm
091: .getNextAttribute(node)) {
092: addAttribute(handler, node);
093: }
094: }
095:
096: /**
097: * Given a result tree fragment, walk the tree and
098: * output it to the SerializationHandler.
099: *
100: * @param obj Result tree fragment object
101: * @param support XPath context for the result tree fragment
102: *
103: * @throws org.xml.sax.SAXException
104: */
105: public static void outputResultTreeFragment(
106: SerializationHandler handler, XObject obj,
107: XPathContext support) throws org.xml.sax.SAXException {
108:
109: int doc = obj.rtf();
110: DTM dtm = support.getDTM(doc);
111:
112: if (null != dtm) {
113: for (int n = dtm.getFirstChild(doc); DTM.NULL != n; n = dtm
114: .getNextSibling(n)) {
115: handler.flushPending();
116:
117: // I think. . . . This used to have a (true) arg
118: // to flush prefixes, will that cause problems ???
119: if (dtm.getNodeType(n) == DTM.ELEMENT_NODE
120: && dtm.getNamespaceURI(n) == null)
121: handler.startPrefixMapping("", "");
122: dtm.dispatchToEvents(n, handler);
123: }
124: }
125: }
126:
127: /**
128: * Copy <KBD>xmlns:</KBD> attributes in if not already in scope.
129: *
130: * As a quick hack to support ClonerToResultTree, this can also be used
131: * to copy an individual namespace node.
132: *
133: * @param src Source Node
134: * NEEDSDOC @param type
135: * NEEDSDOC @param dtm
136: *
137: * @throws TransformerException
138: */
139: public static void processNSDecls(SerializationHandler handler,
140: int src, int type, DTM dtm) throws TransformerException {
141:
142: try {
143: if (type == DTM.ELEMENT_NODE) {
144: for (int namespace = dtm.getFirstNamespaceNode(src,
145: true); DTM.NULL != namespace; namespace = dtm
146: .getNextNamespaceNode(src, namespace, true)) {
147:
148: // String prefix = dtm.getPrefix(namespace);
149: String prefix = dtm.getNodeNameX(namespace);
150: String desturi = handler
151: .getNamespaceURIFromPrefix(prefix);
152: // String desturi = getURI(prefix);
153: String srcURI = dtm.getNodeValue(namespace);
154:
155: if (!srcURI.equalsIgnoreCase(desturi)) {
156: handler.startPrefixMapping(prefix, srcURI,
157: false);
158: }
159: }
160: } else if (type == DTM.NAMESPACE_NODE) {
161: String prefix = dtm.getNodeNameX(src);
162: // Brian M. - some changes here to get desturi
163: String desturi = handler
164: .getNamespaceURIFromPrefix(prefix);
165: String srcURI = dtm.getNodeValue(src);
166:
167: if (!srcURI.equalsIgnoreCase(desturi)) {
168: handler.startPrefixMapping(prefix, srcURI, false);
169: }
170: }
171: } catch (org.xml.sax.SAXException se) {
172: throw new TransformerException(se);
173: }
174: }
175:
176: /**
177: * Returns whether a namespace is defined
178: *
179: *
180: * @param attr Namespace attribute node
181: * @param dtm The DTM that owns attr.
182: *
183: * @return True if the namespace is already defined in
184: * list of namespaces
185: */
186: public static boolean isDefinedNSDecl(
187: SerializationHandler serializer, int attr, DTM dtm) {
188:
189: if (DTM.NAMESPACE_NODE == dtm.getNodeType(attr)) {
190:
191: // String prefix = dtm.getPrefix(attr);
192: String prefix = dtm.getNodeNameX(attr);
193: String uri = serializer.getNamespaceURIFromPrefix(prefix);
194: // String uri = getURI(prefix);
195:
196: if ((null != uri) && uri.equals(dtm.getStringValue(attr)))
197: return true;
198: }
199:
200: return false;
201: }
202:
203: /**
204: * This function checks to make sure a given prefix is really
205: * declared. It might not be, because it may be an excluded prefix.
206: * If it's not, it still needs to be declared at this point.
207: * TODO: This needs to be done at an earlier stage in the game... -sb
208: *
209: * NEEDSDOC @param dtm
210: * NEEDSDOC @param namespace
211: *
212: * @throws org.xml.sax.SAXException
213: */
214: public static void ensureNamespaceDeclDeclared(
215: SerializationHandler handler, DTM dtm, int namespace)
216: throws org.xml.sax.SAXException {
217:
218: String uri = dtm.getNodeValue(namespace);
219: String prefix = dtm.getNodeNameX(namespace);
220:
221: if ((uri != null && uri.length() > 0) && (null != prefix)) {
222: String foundURI;
223: NamespaceMappings ns = handler.getNamespaceMappings();
224: if (ns != null) {
225:
226: foundURI = ns.lookupNamespace(prefix);
227: if ((null == foundURI) || !foundURI.equals(uri)) {
228: handler.startPrefixMapping(prefix, uri, false);
229: }
230: }
231: }
232: }
233: }
|