Home | History | Annotate | Download | only in serialize
      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      */
     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      */
     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      */
    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      */
    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      */
    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      */
    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