< prev index next >

src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/TreeWalker.java

Print this page


   1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package com.sun.org.apache.xml.internal.serializer;
  21 
  22 import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
  23 import java.io.File;
  24 
  25 import com.sun.org.apache.xml.internal.serializer.utils.AttList;
  26 import com.sun.org.apache.xml.internal.serializer.utils.DOM2Helper;

  27 import org.w3c.dom.Comment;
  28 import org.w3c.dom.Element;
  29 import org.w3c.dom.EntityReference;
  30 import org.w3c.dom.NamedNodeMap;
  31 import org.w3c.dom.Node;
  32 import org.w3c.dom.ProcessingInstruction;
  33 import org.w3c.dom.Text;
  34 
  35 import org.xml.sax.ContentHandler;
  36 import org.xml.sax.Locator;
  37 import org.xml.sax.ext.LexicalHandler;
  38 import org.xml.sax.helpers.LocatorImpl;
  39 
  40 /**
  41  * This class does a pre-order walk of the DOM tree, calling a ContentHandler
  42  * interface as it goes.
  43  *
  44  * This class is a copy of the one in com.sun.org.apache.xml.internal.utils.
  45  * It exists to cut the serializers dependancy on that package.
  46  *
  47  * @xsl.usage internal
  48  */
  49 
  50 public final class TreeWalker
  51 {
  52 
  53   /** Local reference to a ContentHandler          */
  54   final private ContentHandler m_contentHandler;
  55   /**
  56    * If m_contentHandler is a SerializationHandler, then this is
  57    * a reference to the same object.
  58    */
  59   final private SerializationHandler m_Serializer;
  60 
  61   // ARGHH!!  JAXP Uses Xerces without setting the namespace processing to ON!
  62   // DOM2Helper m_dh = new DOM2Helper();
  63 
  64   /** DomHelper for this TreeWalker          */
  65   final protected DOM2Helper m_dh;
  66 
  67   /** Locator object for this TreeWalker          */
  68   final private LocatorImpl m_locator = new LocatorImpl();
  69 
  70   /**
  71    * Get the ContentHandler used for the tree walk.
  72    *
  73    * @return the ContentHandler used for the tree walk
  74    */
  75   public ContentHandler getContentHandler()
  76   {
  77     return m_contentHandler;
  78   }
  79 
  80   public TreeWalker(ContentHandler ch) {
  81       this(ch,null);
  82   }
  83   /**
  84    * Constructor.
  85    * @param   contentHandler The implemention of the
  86    * contentHandler operation (toXMLString, digest, ...)
  87    */
  88   public TreeWalker(ContentHandler contentHandler, String systemId)
  89   {
  90       // Set the content handler
  91       m_contentHandler = contentHandler;
  92       if (m_contentHandler instanceof SerializationHandler) {
  93           m_Serializer = (SerializationHandler) m_contentHandler;
  94       } else {
  95           m_Serializer = null;
  96       }
  97       // Set the system ID, if it is given
  98       m_contentHandler.setDocumentLocator(m_locator);
  99       if (systemId != null) {
 100           m_locator.setSystemId(systemId);
 101       }
 102 
 103       m_dh = new DOM2Helper();
 104   }
 105 
 106   /**
 107    * Perform a pre-order traversal non-recursive style.
 108    *
 109    * Note that TreeWalker assumes that the subtree is intended to represent
 110    * a complete (though not necessarily well-formed) document and, during a
 111    * traversal, startDocument and endDocument will always be issued to the
 112    * SAX listener.
 113    *
 114    * @param pos Node in the tree where to start traversal
 115    *
 116    * @throws TransformerException
 117    */
 118   public void traverse(Node pos) throws org.xml.sax.SAXException
 119   {
 120 
 121     this.m_contentHandler.startDocument();
 122 
 123     Node top = pos;


 192         nextNode = pos.getNextSibling();
 193 
 194         if (null == nextNode)
 195         {
 196           pos = pos.getParentNode();
 197 
 198           if ((null == pos) || ((null != top) && top.equals(pos)))
 199           {
 200             nextNode = null;
 201 
 202             break;
 203           }
 204         }
 205       }
 206 
 207       pos = nextNode;
 208     }
 209     this.m_contentHandler.endDocument();
 210   }
 211 
 212   /** Flag indicating whether following text to be processed is raw text          */
 213   boolean nextIsRaw = false;
 214 
 215   /**
 216    * Optimized dispatch of characters.
 217    */
 218   private final void dispatachChars(Node node)
 219      throws org.xml.sax.SAXException
 220   {
 221     if(m_Serializer != null)
 222     {
 223       this.m_Serializer.characters(node);
 224     }
 225     else
 226     {
 227       String data = ((Text) node).getData();
 228       this.m_contentHandler.characters(data.toCharArray(), 0, data.length());
 229     }
 230   }
 231 
 232   /**


 296               String prefix = elem_node.getPrefix();
 297               if (prefix==null)
 298                 prefix="";
 299               this.m_contentHandler.startPrefixMapping(prefix,uri);
 300           }
 301       }
 302       NamedNodeMap atts = elem_node.getAttributes();
 303       int nAttrs = atts.getLength();
 304       // System.out.println("TreeWalker#startNode: "+node.getNodeName());
 305 
 306 
 307       // Make sure the namespace node of
 308       // each attribute is declared to the ContentHandler
 309       for (int i = 0; i < nAttrs; i++)
 310       {
 311         final Node attr = atts.item(i);
 312         final String attrName = attr.getNodeName();
 313         final int colon = attrName.indexOf(':');
 314         final String prefix;
 315 
 316         // System.out.println("TreeWalker#startNode: attr["+i+"] = "+attrName+", "+attr.getNodeValue());
 317         if (attrName.equals("xmlns") || attrName.startsWith("xmlns:"))
 318         {
 319           // Use "" instead of null, as Xerces likes "" for the
 320           // name of the default namespace.  Fix attributed
 321           // to "Steven Murray" <smurray@ebt.com>.
 322           if (colon < 0)
 323             prefix = "";
 324           else
 325             prefix = attrName.substring(colon + 1);
 326 
 327           this.m_contentHandler.startPrefixMapping(prefix,
 328                                                    attr.getNodeValue());
 329         }
 330         else if (colon > 0) {
 331             prefix = attrName.substring(0,colon);
 332             String uri = attr.getNamespaceURI();
 333             if (uri != null)
 334                 this.m_contentHandler.startPrefixMapping(prefix,uri);
 335         }
 336       }
 337 
 338       String ns = m_dh.getNamespaceOfNode(node);
 339       if(null == ns)
 340         ns = "";
 341       this.m_contentHandler.startElement(ns,
 342                                          m_dh.getLocalNameOfNode(node),
 343                                          node.getNodeName(),
 344                                          new AttList(atts, m_dh));
 345       break;
 346     case Node.PROCESSING_INSTRUCTION_NODE :
 347     {
 348       ProcessingInstruction pi = (ProcessingInstruction) node;
 349       String name = pi.getNodeName();
 350 
 351       // String data = pi.getData();
 352       if (name.equals("xslt-next-is-raw"))
 353       {
 354         nextIsRaw = true;
 355       }
 356       else
 357       {
 358         this.m_contentHandler.processingInstruction(pi.getNodeName(),
 359                                                     pi.getData());
 360       }
 361     }
 362     break;
 363     case Node.CDATA_SECTION_NODE :
 364     {


 372       }
 373 
 374       dispatachChars(node);
 375 
 376       {
 377         if (isLexH)
 378         {
 379           lh.endCDATA();
 380         }
 381       }
 382     }
 383     break;
 384     case Node.TEXT_NODE :
 385     {
 386       //String data = ((Text) node).getData();
 387 
 388       if (nextIsRaw)
 389       {
 390         nextIsRaw = false;
 391 
 392         m_contentHandler.processingInstruction(javax.xml.transform.Result.PI_DISABLE_OUTPUT_ESCAPING, "");
 393         dispatachChars(node);
 394         m_contentHandler.processingInstruction(javax.xml.transform.Result.PI_ENABLE_OUTPUT_ESCAPING, "");
 395       }
 396       else
 397       {
 398         dispatachChars(node);
 399       }
 400     }
 401     break;
 402     case Node.ENTITY_REFERENCE_NODE :
 403     {
 404       EntityReference eref = (EntityReference) node;
 405 
 406       if (m_contentHandler instanceof LexicalHandler)
 407       {
 408         ((LexicalHandler) this.m_contentHandler).startEntity(
 409           eref.getNodeName());
 410       }
 411       else
 412       {
 413 
 414         // warning("Can not output entity to a pure SAX ContentHandler");


 419     }
 420   }
 421 
 422   /**
 423    * End processing of given node
 424    *
 425    *
 426    * @param node Node we just finished processing
 427    *
 428    * @throws org.xml.sax.SAXException
 429    */
 430   protected void endNode(Node node) throws org.xml.sax.SAXException
 431   {
 432 
 433     switch (node.getNodeType())
 434     {
 435     case Node.DOCUMENT_NODE :
 436       break;
 437 
 438     case Node.ELEMENT_NODE :
 439       String ns = m_dh.getNamespaceOfNode(node);
 440       if(null == ns)
 441         ns = "";
 442       this.m_contentHandler.endElement(ns,
 443                                          m_dh.getLocalNameOfNode(node),
 444                                          node.getNodeName());
 445 
 446       if (m_Serializer == null) {
 447       // Don't bother with endPrefixMapping calls if the ContentHandler is a
 448       // SerializationHandler because SerializationHandler's ignore the
 449       // endPrefixMapping() calls anyways. . . .  This is an optimization.
 450       Element elem_node = (Element) node;
 451       NamedNodeMap atts = elem_node.getAttributes();
 452       int nAttrs = atts.getLength();
 453 
 454       // do the endPrefixMapping calls in reverse order
 455       // of the startPrefixMapping calls
 456       for (int i = (nAttrs-1); 0 <= i; i--)
 457       {
 458         final Node attr = atts.item(i);
 459         final String attrName = attr.getNodeName();
 460         final int colon = attrName.indexOf(':');
 461         final String prefix;
 462 
 463         if (attrName.equals("xmlns") || attrName.startsWith("xmlns:"))


   1 /*
   2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */

  20 
  21 package com.sun.org.apache.xml.internal.serializer;

  22 
  23 import com.sun.org.apache.xml.internal.utils.AttList;
  24 import com.sun.org.apache.xml.internal.utils.DOM2Helper;
  25 import javax.xml.transform.Result;
  26 import org.w3c.dom.Comment;
  27 import org.w3c.dom.Element;
  28 import org.w3c.dom.EntityReference;
  29 import org.w3c.dom.NamedNodeMap;
  30 import org.w3c.dom.Node;
  31 import org.w3c.dom.ProcessingInstruction;
  32 import org.w3c.dom.Text;

  33 import org.xml.sax.ContentHandler;
  34 import org.xml.sax.Locator;
  35 import org.xml.sax.ext.LexicalHandler;
  36 import org.xml.sax.helpers.LocatorImpl;
  37 
  38 /**
  39  * This class does a pre-order walk of the DOM tree, calling a ContentHandler
  40  * interface as it goes.
  41  *
  42  * This class is a copy of the one in com.sun.org.apache.xml.internal.utils.
  43  * It exists to cut the serializers dependancy on that package.
  44  *
  45  * @xsl.usage internal
  46  */
  47 
  48 public final class TreeWalker
  49 {
  50 
  51   /** Local reference to a ContentHandler          */
  52   final private ContentHandler m_contentHandler;
  53   /**
  54    * If m_contentHandler is a SerializationHandler, then this is
  55    * a reference to the same object.
  56    */
  57   final private SerializationHandler m_Serializer;
  58 






  59   /** Locator object for this TreeWalker          */
  60   final private LocatorImpl m_locator = new LocatorImpl();
  61 
  62   /**
  63    * Get the ContentHandler used for the tree walk.
  64    *
  65    * @return the ContentHandler used for the tree walk
  66    */
  67   public ContentHandler getContentHandler()
  68   {
  69     return m_contentHandler;
  70   }
  71 
  72   public TreeWalker(ContentHandler ch) {
  73       this(ch, null);
  74   }
  75   /**
  76    * Constructor.
  77    * @param   contentHandler The implemention of the
  78    * contentHandler operation (toXMLString, digest, ...)
  79    */
  80   public TreeWalker(ContentHandler contentHandler, String systemId)
  81   {
  82       // Set the content handler
  83       m_contentHandler = contentHandler;
  84       if (m_contentHandler instanceof SerializationHandler) {
  85           m_Serializer = (SerializationHandler) m_contentHandler;
  86       } else {
  87           m_Serializer = null;
  88       }
  89       // Set the system ID, if it is given
  90       m_contentHandler.setDocumentLocator(m_locator);
  91       if (systemId != null) {
  92           m_locator.setSystemId(systemId);
  93       }


  94   }
  95 
  96   /**
  97    * Perform a pre-order traversal non-recursive style.
  98    *
  99    * Note that TreeWalker assumes that the subtree is intended to represent
 100    * a complete (though not necessarily well-formed) document and, during a
 101    * traversal, startDocument and endDocument will always be issued to the
 102    * SAX listener.
 103    *
 104    * @param pos Node in the tree where to start traversal
 105    *
 106    * @throws TransformerException
 107    */
 108   public void traverse(Node pos) throws org.xml.sax.SAXException
 109   {
 110 
 111     this.m_contentHandler.startDocument();
 112 
 113     Node top = pos;


 182         nextNode = pos.getNextSibling();
 183 
 184         if (null == nextNode)
 185         {
 186           pos = pos.getParentNode();
 187 
 188           if ((null == pos) || ((null != top) && top.equals(pos)))
 189           {
 190             nextNode = null;
 191 
 192             break;
 193           }
 194         }
 195       }
 196 
 197       pos = nextNode;
 198     }
 199     this.m_contentHandler.endDocument();
 200   }
 201 
 202   // Flag indicating whether following text to be processed is raw text
 203   boolean nextIsRaw = false;
 204 
 205   /**
 206    * Optimized dispatch of characters.
 207    */
 208   private final void dispatachChars(Node node)
 209      throws org.xml.sax.SAXException
 210   {
 211     if(m_Serializer != null)
 212     {
 213       this.m_Serializer.characters(node);
 214     }
 215     else
 216     {
 217       String data = ((Text) node).getData();
 218       this.m_contentHandler.characters(data.toCharArray(), 0, data.length());
 219     }
 220   }
 221 
 222   /**


 286               String prefix = elem_node.getPrefix();
 287               if (prefix==null)
 288                 prefix="";
 289               this.m_contentHandler.startPrefixMapping(prefix,uri);
 290           }
 291       }
 292       NamedNodeMap atts = elem_node.getAttributes();
 293       int nAttrs = atts.getLength();
 294       // System.out.println("TreeWalker#startNode: "+node.getNodeName());
 295 
 296 
 297       // Make sure the namespace node of
 298       // each attribute is declared to the ContentHandler
 299       for (int i = 0; i < nAttrs; i++)
 300       {
 301         final Node attr = atts.item(i);
 302         final String attrName = attr.getNodeName();
 303         final int colon = attrName.indexOf(':');
 304         final String prefix;
 305 

 306         if (attrName.equals("xmlns") || attrName.startsWith("xmlns:"))
 307         {
 308           // Use "" instead of null, as Xerces likes "" for the
 309           // name of the default namespace.  Fix attributed
 310           // to "Steven Murray" <smurray@ebt.com>.
 311           if (colon < 0)
 312             prefix = "";
 313           else
 314             prefix = attrName.substring(colon + 1);
 315 
 316           this.m_contentHandler.startPrefixMapping(prefix,
 317                                                    attr.getNodeValue());
 318         }
 319         else if (colon > 0) {
 320             prefix = attrName.substring(0,colon);
 321             String uri = attr.getNamespaceURI();
 322             if (uri != null)
 323                 this.m_contentHandler.startPrefixMapping(prefix,uri);
 324         }
 325       }
 326 
 327       String ns = DOM2Helper.getNamespaceOfNode(node);
 328       if(null == ns)
 329         ns = "";
 330       this.m_contentHandler.startElement(ns,
 331                                          DOM2Helper.getLocalNameOfNode(node),
 332                                          node.getNodeName(),
 333                                          new AttList(atts));
 334       break;
 335     case Node.PROCESSING_INSTRUCTION_NODE :
 336     {
 337       ProcessingInstruction pi = (ProcessingInstruction) node;
 338       String name = pi.getNodeName();
 339 
 340       // String data = pi.getData();
 341       if (name.equals("xslt-next-is-raw"))
 342       {
 343         nextIsRaw = true;
 344       }
 345       else
 346       {
 347         this.m_contentHandler.processingInstruction(pi.getNodeName(),
 348                                                     pi.getData());
 349       }
 350     }
 351     break;
 352     case Node.CDATA_SECTION_NODE :
 353     {


 361       }
 362 
 363       dispatachChars(node);
 364 
 365       {
 366         if (isLexH)
 367         {
 368           lh.endCDATA();
 369         }
 370       }
 371     }
 372     break;
 373     case Node.TEXT_NODE :
 374     {
 375       //String data = ((Text) node).getData();
 376 
 377       if (nextIsRaw)
 378       {
 379         nextIsRaw = false;
 380 
 381         m_contentHandler.processingInstruction(Result.PI_DISABLE_OUTPUT_ESCAPING, "");
 382         dispatachChars(node);
 383         m_contentHandler.processingInstruction(Result.PI_ENABLE_OUTPUT_ESCAPING, "");
 384       }
 385       else
 386       {
 387         dispatachChars(node);
 388       }
 389     }
 390     break;
 391     case Node.ENTITY_REFERENCE_NODE :
 392     {
 393       EntityReference eref = (EntityReference) node;
 394 
 395       if (m_contentHandler instanceof LexicalHandler)
 396       {
 397         ((LexicalHandler) this.m_contentHandler).startEntity(
 398           eref.getNodeName());
 399       }
 400       else
 401       {
 402 
 403         // warning("Can not output entity to a pure SAX ContentHandler");


 408     }
 409   }
 410 
 411   /**
 412    * End processing of given node
 413    *
 414    *
 415    * @param node Node we just finished processing
 416    *
 417    * @throws org.xml.sax.SAXException
 418    */
 419   protected void endNode(Node node) throws org.xml.sax.SAXException
 420   {
 421 
 422     switch (node.getNodeType())
 423     {
 424     case Node.DOCUMENT_NODE :
 425       break;
 426 
 427     case Node.ELEMENT_NODE :
 428       String ns = DOM2Helper.getNamespaceOfNode(node);
 429       if(null == ns)
 430         ns = "";
 431       this.m_contentHandler.endElement(ns,
 432               DOM2Helper.getLocalNameOfNode(node),
 433               node.getNodeName());
 434 
 435       if (m_Serializer == null) {
 436       // Don't bother with endPrefixMapping calls if the ContentHandler is a
 437       // SerializationHandler because SerializationHandler's ignore the
 438       // endPrefixMapping() calls anyways. . . .  This is an optimization.
 439       Element elem_node = (Element) node;
 440       NamedNodeMap atts = elem_node.getAttributes();
 441       int nAttrs = atts.getLength();
 442 
 443       // do the endPrefixMapping calls in reverse order
 444       // of the startPrefixMapping calls
 445       for (int i = (nAttrs-1); 0 <= i; i--)
 446       {
 447         final Node attr = atts.item(i);
 448         final String attrName = attr.getNodeName();
 449         final int colon = attrName.indexOf(':');
 450         final String prefix;
 451 
 452         if (attrName.equals("xmlns") || attrName.startsWith("xmlns:"))


< prev index next >