1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.sonar.plugins.utils;
21
22 import org.apache.commons.io.IOUtils;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25 import org.w3c.dom.Document;
26 import org.w3c.dom.Element;
27 import org.w3c.dom.Node;
28 import org.w3c.dom.NodeList;
29 import org.xml.sax.SAXException;
30
31 import javax.xml.namespace.QName;
32 import javax.xml.parsers.DocumentBuilder;
33 import javax.xml.parsers.DocumentBuilderFactory;
34 import javax.xml.parsers.ParserConfigurationException;
35 import javax.xml.xpath.XPath;
36 import javax.xml.xpath.XPathConstants;
37 import javax.xml.xpath.XPathExpression;
38 import javax.xml.xpath.XPathExpressionException;
39 import javax.xml.xpath.XPathFactory;
40 import java.io.BufferedReader;
41 import java.io.ByteArrayInputStream;
42 import java.io.File;
43 import java.io.FileReader;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.InputStreamReader;
47 import java.util.ArrayList;
48 import java.util.HashMap;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.regex.Matcher;
52 import java.util.regex.Pattern;
53
54 public class XmlReportParser {
55
56 private Element root = null;
57 private Document doc = null;
58 private DocumentBuilder builder;
59 private XPathFactory factory;
60 private XPath xpath;
61 private Map<String, XPathExpression> compiledExprs = new HashMap<String, XPathExpression>();
62
63 public XmlReportParser() {
64 DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
65 try {
66 bf.setFeature("http://apache.org/xml/features/validation/schema", false);
67 bf.setFeature("http://xml.org/sax/features/external-general-entities", false);
68 bf.setFeature("http://xml.org/sax/features/validation", false);
69 bf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
70 bf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
71 bf.setFeature("http://apache.org/xml/features/allow-java-encodings", true);
72 } catch (ParserConfigurationException e) {
73 Logger log = LoggerFactory.getLogger(this.getClass().getName());
74 log.error("Error occured during features set up.", e);
75 }
76 try {
77 bf.setNamespaceAware(false);
78 bf.setValidating(false);
79 builder = bf.newDocumentBuilder();
80 } catch (ParserConfigurationException e) {
81 throw new XmlParserException("can not instance a XML parser", e);
82 }
83 }
84
85 public void parse(File file) {
86 try {
87 BufferedReader buffer = new BufferedReader(new FileReader(file));
88 parse(buffer);
89 } catch (IOException e) {
90 throw new XmlParserException("can not parse the file " + file.getAbsolutePath(), e);
91 }
92 }
93
94 public void parse(InputStream stream) {
95 try {
96 BufferedReader buffer = new BufferedReader(new InputStreamReader(stream));
97 parse(buffer);
98 } catch (IOException e) {
99 throw new XmlParserException("can not parse the stream", e);
100 }
101 }
102
103 private void parse(BufferedReader buffer) throws IOException {
104 parse(IOUtils.toString(buffer));
105 }
106
107 public void parse(String xml) {
108 try {
109 xml = fixUnicodeChar(xml);
110 doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
111 factory = XPathFactory.newInstance();
112 xpath = factory.newXPath();
113
114 } catch (SAXException e) {
115 throw new XmlParserException("can not parse xml : " + xml, e);
116 } catch (IOException e) {
117 throw new XmlParserException("can not parse xml : " + xml, e);
118 }
119 }
120
121 public Element getRoot() {
122 if (root == null && doc != null) {
123 root = doc.getDocumentElement();
124 }
125 return root;
126 }
127
128 public Document getDocument() {
129 return doc;
130 }
131
132 public Element getChildElement(Element base, String elementName) {
133 NodeList childrens = base.getElementsByTagName(elementName);
134 for (int i = 0; i < childrens.getLength(); i++) {
135 Node nde = childrens.item(i);
136 if (nde.getNodeType() == Node.ELEMENT_NODE) {
137 return (Element) nde;
138 }
139 }
140 return null;
141 }
142
143 public Element getChildElement(String elementName) {
144 NodeList childrens = getRoot().getElementsByTagName(elementName);
145 for (int i = 0; i < childrens.getLength(); i++) {
146 Node nde = childrens.item(i);
147 if (nde.getNodeType() == Node.ELEMENT_NODE) {
148 return (Element) nde;
149 }
150 }
151 return null;
152 }
153
154 public List<Element> getChildElements(String elementName) {
155 List<Element> rtrVal = new ArrayList<Element>();
156 NodeList childrens = getRoot().getElementsByTagName(elementName);
157 for (int i = 0; i < childrens.getLength(); i++) {
158 Node nde = childrens.item(i);
159 if (nde.getNodeType() == Node.ELEMENT_NODE) {
160 rtrVal.add((Element) nde);
161 }
162 }
163 return rtrVal;
164 }
165
166 public List<Element> getChildElements(Element base, String elementName) {
167 List<Element> rtrVal = new ArrayList<Element>();
168 NodeList childrens = base.getElementsByTagName(elementName);
169 for (int i = 0; i < childrens.getLength(); i++) {
170 Node nde = childrens.item(i);
171 if (nde.getNodeType() == Node.ELEMENT_NODE) {
172 rtrVal.add((Element) nde);
173 }
174 }
175 return rtrVal;
176 }
177
178 public String getChildElementValue(Element base, String elementName) {
179 NodeList childrens = base.getElementsByTagName(elementName);
180 for (int i = 0; i < childrens.getLength(); i++) {
181 if (childrens.item(i).getNodeType() == Node.ELEMENT_NODE) {
182 return childrens.item(i).getFirstChild().getNodeValue();
183 }
184 }
185 return null;
186 }
187
188 public String getElementValue(Node base) {
189 if ( base.getNextSibling() != null && base.getNextSibling().getNodeType() == Node.TEXT_NODE ) {
190 return base.getNextSibling().getNodeValue();
191 } else if ( base.getFirstChild() != null && base.getFirstChild().getNodeType() == Node.TEXT_NODE ) {
192 return base.getFirstChild().getNodeValue();
193 }
194 return null;
195 }
196
197 public String getChildElementValue(String elementName) {
198 NodeList childrens = getRoot().getElementsByTagName(elementName);
199 for (int i = 0; i < childrens.getLength(); i++) {
200 if (childrens.item(i).getNodeType() == Node.ELEMENT_NODE) {
201 return childrens.item(i).getFirstChild().getNodeValue();
202 }
203 }
204 return null;
205 }
206
207 public Object executeXPath(Node node, QName qname, String xPathExpression) {
208 XPathExpression expr = compiledExprs.get(xPathExpression);
209 try {
210 if ( expr == null ) {
211 expr = xpath.compile(xPathExpression);
212 compiledExprs.put(xPathExpression, expr);
213 }
214 return expr.evaluate(node, qname);
215 } catch (XPathExpressionException e) {
216 throw new XmlParserException("Unable to evaluate xpath expression :" + xPathExpression, e);
217 }
218 }
219
220 public String executeXPath(String xPathExpression) {
221 return (String) executeXPath(doc, XPathConstants.STRING, xPathExpression);
222 }
223
224 public String executeXPath(Node node, String xPathExpression) {
225 return (String) executeXPath(node, XPathConstants.STRING, xPathExpression);
226 }
227
228 public NodeList executeXPathNodeList(String xPathExpression) {
229 return (NodeList) executeXPath(doc, XPathConstants.NODESET, xPathExpression);
230 }
231
232 public NodeList executeXPathNodeList(Node node, String xPathExpression) {
233 return (NodeList) executeXPath(node, XPathConstants.NODESET, xPathExpression);
234 }
235
236 public Node executeXPathNode(Node node, String xPathExpression) {
237 return (Node) executeXPath(node, XPathConstants.NODE, xPathExpression);
238 }
239
240
241
242
243
244 protected String fixUnicodeChar(String text){
245 String unicode = "&u";
246 StringBuilder replace = new StringBuilder(text);
247 if (text.indexOf(unicode) >= 0) {
248 Pattern p = Pattern.compile("&u([0-9a-fA-F]{1,4});");
249 Matcher m = p.matcher(replace.toString());
250 int nbFind = 0;
251 while (m.find()) {
252
253 replace.replace(m.start() + nbFind, m.end() + nbFind, "&#x" + m.group(1) + ";");
254 nbFind++;
255 }
256 }
257 return replace.toString();
258 }
259 }