Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * This file is part of the DiffX library.
   *
   * For licensing information please see the file license.txt included in the release.
   * A copy of this licence can also be found at
   *   http://www.opensource.org/licenses/artistic-license-2.0.php
   */
  package com.topologi.diffx.load;
  
 import java.io.File;
 import java.util.List;
 
 
 
Loads a DOM documents as a sequence of events.

This class implements the methods Recorder.process(java.io.File) and Recorder.process(java.lang.String) for convenience, but is it much more efficient to feed this recorder directly with a DOM.

This class is not synchronised.

Author(s):
Christophe Lauret
Version:
10 May 2010
Since:
0.7
 
 public final class DOMRecorder implements XMLRecorder {
 
   // class attributes -------------------------------------------------------------------------------
 
  
The DiffX configuration to use
 
   private DiffXConfig config = new DiffXConfig();
 
   // state variables --------------------------------------------------------------------------------
 
  
The factory that will produce events according to the configuration.
 
   private transient EventFactory efactory;

  
The text tokenizer used by this recorder.
 
   private transient TextTokenizer tokenizer;

  
The sequence of event for this recorder.
 
   private transient EventSequence sequence;

  
The sequence of event for this recorder.
 
   private transient PrefixMapping mapping;

  
The weight of the current element.
 
   private transient int currentWeight = -1;

  
The stack of events' weight, should only contain Integer.
 
   private transient List<Integerweights = new ArrayList<Integer>();

  
Indicates whether the given document is a fragment.

An fragment is a portion of XML that is not necessarily well-formed by itself, because the namespace has been declared higher in the hierarchy, in which if the DOM tree was serialised it would not produce well-formed XML.

This option indicates that the recorder should try to generate the prefix mapping without the declaration.

  private transient boolean isFragment = true;
  // methods ----------------------------------------------------------------------------------------

  
Returns the configuration used by this recorder.

Returns:
the configuration used by this recorder.
  public DiffXConfig getConfig() {
    return this.;
  }

  
Sets the configuration used by this recorder.

Parameters:
config The configuration used by this recorder.
  public void setConfig(DiffXConfig config) {
    this. = config;
  }

  
  public EventSequence process(File filethrows LoadingExceptionIOException {
    InputStream in = new BufferedInputStream(new FileInputStream(file));
    return process(new InputSource(in));
  }

  
  public EventSequence process(String xmlthrows LoadingException {
    return process(new InputSource(new StringReader(xml)));
  }

  
Runs the recorder on the specified input source.

Parameters:
is The input source.
Returns:
The recorded sequence of events.
Throws:
LoadingException If thrown while parsing.
    this. = false// input source is not a fragment
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    dbFactory.setNamespaceAware(this..isNamespaceAware());
    dbFactory.setExpandEntityReferences(true);
    dbFactory.setValidating(false);
    try {
      DocumentBuilder builder = dbFactory.newDocumentBuilder();
      Document document = builder.parse(is);
      return this.process(document);
    } catch (Exception ex) {
      throw new LoadingException(ex);
    }
  }

  
Processes the given node and returns the corresponding event sequence.

Parameters:
node The W3C DOM node to be processed.
Returns:
The recorded sequence of events.
Throws:
LoadingException If thrown while parsing.
  public EventSequence process(Node nodethrows LoadingException {
    // initialise the state variables.
    this. = new EventFactory(this..isNamespaceAware());
    this. = TokenizerFactory.get(this.);
    this. = new EventSequence();
    this. = this..getPrefixMapping();
    // start processing the nodes
    loadNode(node);
    this. = true;
    return this.;
  }

  
Processes the given node list and returns the corresponding event sequence.

This method only returns the event sequence from the first node in the node list, if the node list is empty, this method returns an empty sequence.

Parameters:
node The W3C DOM node to be processed.
Returns:
The recorded sequence of events.
Throws:
LoadingException If thrown while parsing.
  public EventSequence process(NodeList nodethrows LoadingException {
    if (node.getLength() == 0)
      return new EventSequence();
    return process(node.item(0));
  }
  // specific loaders ---------------------------------------------------------------------

  
Loads the given node in the current sequence.

Parameters:
node The W3C DOM node to load.
Throws:
LoadingException If thrown while parsing.
  private void loadNode(Node nodethrows LoadingException {
    // dispatch to the correct loader performance: order by occurrence
    if (node instanceof Element) {
      load((Element)node);
    }
    if (node instanceof Text) {
      load((Text)node);
    } else if (node instanceof Attr) {
      load((Attr)node);
    } else if (node instanceof Document) {
      load((Document)node);
    } else if (node instanceof ProcessingInstruction) {
      load((ProcessingInstruction)node);
      // all other node types are ignored
    }
  }

  
Loads the given document in the current sequence.

Parameters:
document The W3C DOM document node to load.
Throws:
LoadingException If thrown while parsing.
  private void load(Document documentthrows LoadingException {
    load(document.getDocumentElement());
  }

  
Loads the given element in the current sequence.

Parameters:
element The W3C DOM element node to load.
Throws:
LoadingException If thrown while parsing.
  private void load(Element elementthrows LoadingException {
    if (this. > 0) {
      this..add(Integer.valueOf(this.));
    }
    this. = 1;
    // namespace handling
    OpenElementEvent open = null;
    // namespace aware configuration
    if (this..isNamespaceAware()) {
      String uri = element.getNamespaceURI() == null"" : element.getNamespaceURI();
      String name = element.getLocalName();
      handlePrefixMapping(urielement.getPrefix());
      open = this..makeOpenElement(uriname);
      // not namespace aware
    } else {
      open = this..makeOpenElement(nullelement.getNodeName());
    }
    this..addEvent(open);
    NamedNodeMap atts = element.getAttributes();
    // only 1 attribute, just load it
    if (atts.getLength() == 1) {
      load((Attr)atts.item(0));
      // several attributes sort them in alphabetical order
      // TODO: also use URI
    } else if (atts.getLength() > 1) {
      String[] names = new String[atts.getLength()];
      for (int i = 0; i < atts.getLength(); i++) {
        Attr attr = (Attr)atts.item(i);
        names[i] = attr.getName();
      }
      Arrays.sort(names);
      for (String name : names) {
        load((Attr)atts.getNamedItem(name));
      }
    }
    // load all the child nodes
    NodeList list = element.getChildNodes();
    for (int i = 0; i < list.getLength(); i++) {
      loadNode(list.item(i));
    }
    CloseElementEvent close = this..makeCloseElement(open);
    this..addEvent(close);
    // handle the weights
    close.setWeight(this.);
    open.setWeight(this.);
    this. += popWeight();
  }

  
Loads the given text in the current sequence depending on the configuration.

Parameters:
text The W3C DOM text node to load.
Throws:
LoadingException If thrown while parsing.
  private void load(Text textthrows LoadingException {
    List<TextEventevents = this..tokenize(text.getData());
    for (TextEvent e : events) {
      this..addEvent(e);
    }
    this. += events.size();
  }

  
Loads the given processing instruction in the current sequence.

Parameters:
pi The W3C DOM PI node to load.
Throws:
LoadingException If thrown while parsing.
  private void load(ProcessingInstruction pithrows LoadingException {
    this.++;
  }

  
Returns the last weight and remove it from the stack.

Returns:
The weight on top of the stack.
  private int popWeight() {
    if (this..size() > 0)
      return ((Integer)this..remove(this..size() - 1)).intValue();
    else
      return 0;
  }

  
Loads the given attribute in the current sequence.

Parameters:
attr The W3C DOM attribute node to load.
  private void load(Attr attr) {
        attr.getLocalName(),
        attr.getNodeName(),
        attr.getValue()));
  }

  
Loads the given attribute in the current sequence.

Parameters:
e An attribute event.
  private void load(AttributeEvent e) {
    // a namespace declaration, translate the event into a prefix mapping
    if ("http://www.w3.org/2000/xmlns/".equals(e.getURI())) {
      this..mapPrefix(e.getValue(), e.getName());
      // a regular attribute
    } else {
      e.setWeight(2);
      this. += 2;
      this..addEvent(e);
    }
  }

  
Handles the prefix mapping. If the current process is working on a fragment,

Parameters:
uri The namespace URI.
prefix The prefix used for the namespace.
  private void handlePrefixMapping(String uriString prefix) {
    if (this.) {
      if (this..getPrefix(uri) != nullreturn;
      if (prefix == null && !"".equals(uri)) {
        this..add(uri"");
      } else if (prefix != null && !"xmlns".equals(prefix)) {
        this..add(uriprefix);
      }
    }
  }
New to GrepCode? Check out our FAQ X