package eu.choreos.vv.clientgenerator; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.HashMap; import java.util.Stack; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.xerces.impl.Constants; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.ext.DefaultHandler2; import eu.choreos.vv.exceptions.ParserException; /** * Utility class to parse the Soap XML response of a Web Service operation * * @author Leonardo Leite, Guilherme Nogueira * */ public class ItemParser { private static SAXParserFactory parserFactory = SAXParserFactory.newInstance(); private SAXParser parser; private ItemImpl result; private class ResponseParserHandler extends DefaultHandler2 { private Stack<ItemImpl> tagStack = new Stack<ItemImpl>(); /** * @param ch - The characters. * @param start - The start position in the character array. * @param length - The number of characters to use from the character array. */ @Override public void characters(char[] ch, int start, int lenght) throws SAXException { String trimmed = new String(ch, start, lenght).trim(); if (!trimmed.isEmpty() && !tagStack.empty()) { tagStack.peek().appendContent(trimmed); } } /** * @param uri - The Namespace URI. * @param localName - The local name (without prefix). * @param qName - The qualified name (with prefix). */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (!tagStack.empty()) { ItemImpl poped = tagStack.pop(); if (!tagStack.empty()){ ItemImpl father = tagStack.peek(); father.addChild(poped); } else { result = poped; } } } /** * @param uri - The Namespace URI. * @param localName - The local name (without prefix). * @param qName - The qualified name (with prefix). * @param attributes - The attributes attached to the element. */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { String name = getNameWithoutNamespace(qName); if (doNotContainsHeaderInformation(name) || !tagStack.empty()) { HashMap<String, String> parameters = new HashMap<String, String>(); for(int i=0; i< attributes.getLength(); i++) parameters.put(attributes.getQName(i), attributes.getValue(i)); result = new ItemImpl(name, parameters); tagStack.push(result); } } @Override public void startCDATA() throws SAXException { if (!tagStack.empty()) { tagStack.peek().setContentCDATA(true); } } private boolean doNotContainsHeaderInformation(String name) { return !name.contains("Envelope")&&!name.contains("Header")&&!name.contains("Body"); } private String getNameWithoutNamespace(String qName) { String[] names = qName.split(":"); return names[names.length - 1]; } } /** Property id: lexical handler. */ protected static final String LEXICAL_HANDLER = Constants.SAX_PROPERTY_PREFIX + Constants.LEXICAL_HANDLER_PROPERTY; public Item parse(String xml) throws ParserException { try { if (xml == null) return null; InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8")); ResponseParserHandler handler = new ResponseParserHandler(); parser = parserFactory.newSAXParser(); parser.setProperty(LEXICAL_HANDLER, handler); parser.parse(is, handler); } catch (Exception e) { throw new ParserException(e); } return result; } }