1 package org.opensrf.util;
3 import javax.xml.stream.*;
4 import javax.xml.stream.events.* ;
5 import javax.xml.namespace.QName;
7 import java.util.HashMap;
9 import java.util.ArrayList;
10 import java.util.ListIterator;
11 import java.io.InputStream;
12 import org.opensrf.util.JSONWriter;
13 import org.opensrf.util.JSONReader;
16 * Flattens an XML file into a properties map. Values are stored as JSON strings or arrays.
17 * An array is created if more than one value resides at the same key.
18 * e.g. html.head.script = "alert('hello');"
20 public class XMLFlattener {
22 /** Flattened properties map */
23 private Map<String, String> props;
24 /** Incoming XML stream */
25 private InputStream inStream;
26 /** Runtime list of encountered elements */
27 private List<String> elementList;
30 * Creates a new reader. Initializes the message queue.
31 * Sets the stream state to disconnected, and the xml
32 * state to in_nothing.
33 * @param inStream the inbound XML stream
35 public XMLFlattener(InputStream inStream) {
36 props = new HashMap<String, String>();
37 this.inStream = inStream;
38 elementList = new ArrayList<String>();
41 /** Turns an array of strings into a dot-separated key string */
42 private String listToString() {
43 ListIterator itr = elementList.listIterator();
44 StringBuffer sb = new StringBuffer();
45 while(itr.hasNext()) {
46 sb.append(itr.next());
54 * Parses XML data from the provided stream.
56 public Map read() throws javax.xml.stream.XMLStreamException {
58 XMLInputFactory factory = XMLInputFactory.newInstance();
60 /** disable as many unused features as possible to speed up the parsing */
61 factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.TRUE);
62 factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
63 factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);
64 factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE);
65 factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
67 /** create the stream reader */
68 XMLStreamReader reader = factory.createXMLStreamReader(inStream);
71 while(reader.hasNext()) {
72 /** cycle through the XML events */
74 eventType = reader.next();
75 if(reader.isWhiteSpace()) continue;
79 case XMLEvent.START_ELEMENT:
80 elementList.add(reader.getName().toString());
83 case XMLEvent.CHARACTERS:
84 String text = reader.getText();
85 String key = listToString();
87 if(props.containsKey(key)) {
89 /* something in the map already has this key */
93 o = new JSONReader(props.get(key)).read();
94 } catch(org.opensrf.util.JSONException e){}
96 if(o instanceof List) {
97 /* if the map contains a list, append to the list and re-encode */
101 /* if the map just contains a string, start building a new list
102 * with the old string and append the new string */
103 List<String> arr = new ArrayList<String>();
109 props.put(key, new JSONWriter(o).write());
112 props.put(key, new JSONWriter(text).write());
116 case XMLEvent.END_ELEMENT:
117 elementList.remove(elementList.size()-1);