1 package com.netflix.api.utils;
2
3 import java.io.BufferedReader;
4 import java.io.ByteArrayInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
8 import java.io.OutputStream;
9 import java.io.StringReader;
10 import java.io.StringWriter;
11 import java.io.UnsupportedEncodingException;
12 import java.util.List;
13 import java.util.StringTokenizer;
14
15 import javax.xml.transform.Transformer;
16 import javax.xml.transform.TransformerFactory;
17 import javax.xml.transform.stream.StreamResult;
18 import javax.xml.transform.stream.StreamSource;
19 import javax.xml.xpath.XPathConstants;
20 import javax.xml.xpath.XPathExpression;
21 import javax.xml.xpath.XPathFactory;
22
23 import org.apache.commons.io.IOUtils;
24 import org.jaxen.JaxenException;
25 import org.jdom.Attribute;
26 import org.jdom.Document;
27 import org.jdom.Element;
28 import org.jdom.IllegalDataException;
29 import org.jdom.IllegalNameException;
30 import org.jdom.JDOMException;
31 import org.jdom.Parent;
32 import org.jdom.input.SAXBuilder;
33 import org.jdom.output.Format;
34 import org.jdom.output.XMLOutputter;
35 import org.jdom.xpath.XPath;
36 import org.slf4j.LoggerFactory;
37 import org.slf4j.Logger;
38 import org.xml.sax.InputSource;
39
40
41
42
43
44
45 public class XMLUtils
46 {
47 private static final Logger logger = LoggerFactory.getLogger(XMLUtils.class);
48
49 private static final String DEFAULT_ENCODING = "UTF-8";
50
51 private static XPathFactory xPathFactory;
52
53 private static javax.xml.xpath.XPath xPathInstance;
54
55 static
56 {
57 xPathFactory = XPathFactory.newInstance();
58 try
59 {
60 xPathInstance = xPathFactory.newXPath();
61 }
62 catch (Exception e)
63 {
64 logger.error("Could not instantiate XPath due to exception", e);
65 }
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79
80 public static String applyStylesheetAsString(String xmlString, String xsltStr) throws Exception
81 {
82
83
84
85
86
87 TransformerFactory tFactory = TransformerFactory.newInstance();
88
89
90
91
92
93 Transformer transformer = tFactory.newTransformer(new StreamSource(new ByteArrayInputStream(xsltStr.getBytes())));
94
95
96
97
98 StringWriter swriter = new StringWriter();
99 StreamResult sresult = new StreamResult(swriter);
100 transformer.transform(new StreamSource(new ByteArrayInputStream(xmlString.getBytes("UTF-8"))), sresult);
101 return swriter.toString();
102 }
103
104
105
106
107
108
109
110
111
112
113 public static String applyStylesheetAsFile(String xmlString, String xslFileName) throws Exception
114 {
115 logger.debug("XMLUtils: applyStylesheetAsFile() - fileName: " + xslFileName);
116
117 try
118 {
119 InputStream is = XMLUtils.class.getResourceAsStream(xslFileName);
120 byte[] xslBytes = IOUtils.toByteArray(is);
121 String xslString = new String(xslBytes);
122 xmlString = applyStylesheetAsString(xmlString, xslString);
123 } catch (Exception e)
124 {
125 logger.error("Exception caught in applyStylesheetAsFile " + e.getMessage());
126 throw e;
127 }
128 return xmlString;
129 }
130
131
132
133
134
135
136
137
138
139
140 public static String getAttribute(Element elem, String attributeName) throws Exception
141 {
142 String value = elem.getAttributeValue(attributeName);
143 return value;
144 }
145
146
147
148
149
150
151
152
153
154
155
156 public static String RootAttribute(String xmlString, String attributeName) throws Exception
157 {
158 Document doc = createDocumentFromString(xmlString);
159 String value = getRootAttribute(doc, attributeName);
160 return value;
161 }
162
163
164
165
166
167
168
169
170
171
172 public static Document createDocumentFromString(String xmlString) throws JDOMException, IOException
173 {
174 Document schemaDoc = null;
175 SAXBuilder builder = new SAXBuilder(false);
176 byte[] xmlBytes = null;
177 try
178 {
179
180 xmlBytes = xmlString.getBytes(DEFAULT_ENCODING);
181 schemaDoc = builder.build(new ByteArrayInputStream(xmlBytes));
182 } catch (UnsupportedEncodingException usee)
183 {
184 schemaDoc = builder.build(new StringReader(xmlString));
185 }
186 return schemaDoc;
187 }
188
189
190
191
192
193
194
195
196 public static Document createDocumentFromString(String xmlString, String encoding) throws JDOMException, IOException
197 {
198 Document schemaDoc = null;
199 SAXBuilder builder = new SAXBuilder(false);
200 byte[] xmlBytes = null;
201 try
202 {
203 xmlBytes = xmlString.getBytes(encoding);
204 schemaDoc = builder.build(new ByteArrayInputStream(xmlBytes));
205 } catch (UnsupportedEncodingException usee)
206 {
207 schemaDoc = builder.build(new StringReader(xmlString));
208 }
209 return schemaDoc;
210 }
211
212
213
214
215
216
217
218
219
220
221 public static Document createDocumentFromStream(InputStream inputStream) throws UnsupportedEncodingException, JDOMException, IOException
222 {
223 Document xmlDoc = null;
224 SAXBuilder builder = new SAXBuilder(false);
225 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, DEFAULT_ENCODING));
226 xmlDoc = builder.build(new InputSource(reader));
227 return xmlDoc;
228 }
229
230
231
232
233
234
235
236
237 public static boolean isSet(String s)
238 {
239 return ((s != null) && (!s.equals("")));
240 }
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259 public static void addAttribute(Document xmlDoc, String xPath, String name, String value) throws Exception
260 {
261 Element e;
262 XPath xpath1;
263 xpath1 = XPath.newInstance(xPath);
264 e = (Element) xpath1.selectSingleNode(xmlDoc);
265 if (e != null)
266 {
267 e.setAttribute(name, value);
268 }
269 }
270
271
272
273
274
275
276
277
278
279
280
281
282 public static Element addElement(Document xmlDoc, String xPath)
283 {
284 Element root = null;
285 Element currentElem = null;
286 Element tmpElem = null;
287 root = xmlDoc.getRootElement();
288
289
290 StringTokenizer tok = new StringTokenizer(xPath, "/");
291
292 int numNodes = tok.countTokens() - 1;
293 if (numNodes < 0)
294 numNodes = 0;
295
296
297 currentElem = root;
298 for (int i = 0; i < numNodes; i++)
299 {
300 String parentTagName = (String) tok.nextToken();
301 tmpElem = currentElem.getChild(parentTagName);
302 if (tmpElem == null)
303 {
304
305 tmpElem = new Element(parentTagName);
306 currentElem.addContent(tmpElem);
307 }
308 currentElem = tmpElem;
309 }
310 return tmpElem;
311 }
312
313
314
315
316
317
318
319
320
321
322
323 public static void addElementValue(Element element, String value)
324 {
325 if (element == null)
326 return;
327 element.setText(value);
328 }
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344 public static void addElementValue(Document xmlDoc, String xPath, String value) throws Exception
345 {
346 Element e;
347 XPath xpath1;
348 xpath1 = XPath.newInstance(xPath);
349 e = (Element) xpath1.selectSingleNode(xmlDoc);
350 if (e != null)
351 {
352 e.setText(value);
353 }
354 else
355 {
356 addElement(xmlDoc, xPath);
357 e = (Element) xpath1.selectSingleNode(xmlDoc);
358 if (e == null)
359 {
360 logger.error("XMLUtils: addElementValue. "
361 + " Unable to add element " + xPath
362 + " to document.");
363 return;
364 }
365 e.setText(value);
366 }
367 }
368
369
370
371
372
373
374
375
376
377
378 public static void addRootAttribute(Document xmlDoc, String name, String value) throws Exception
379 {
380 Element root = xmlDoc.getRootElement();
381 if (root != null)
382 root.setAttribute(name, value);
383 }
384
385
386
387
388
389
390
391
392 public void addRootNamespace(Document xmlDoc, String namespace)
393 {
394 Element root = xmlDoc.getRootElement();
395 if (root != null)
396 root.setNamespace(org.jdom.Namespace.getNamespace(namespace));
397 }
398
399
400
401
402
403
404
405
406
407
408
409
410 public static void deleteElementGivenXPath(Document xmlDoc, String xPath) throws JDOMException
411 {
412 Element e;
413 XPath xpath1;
414 xpath1 = XPath.newInstance(xPath);
415 e = (Element) xpath1.selectSingleNode(xmlDoc);
416 if (e != null)
417 {
418 Parent parentElement = e.getParent();
419 if (parentElement != null)
420 {
421 parentElement.removeContent(e);
422 }
423 }
424 else
425 {
426 logger.warn("XMLUtils:deleteElementGivenXPath. There is no such element for: " + xPath);
427 }
428 }
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443 public static String getElementTextFromString(String docString, String start)
444 {
445 String tmp = "<" + start + ">";
446 int begin = docString.indexOf(tmp);
447 if (begin == -1)
448 {
449 logger.error("XMLUtils:getElementTextFromString: "
450 + " Unable to find <" + start + "> in string.");
451 return null;
452 }
453
454 int end = docString.indexOf("</", begin);
455 if (end == -1)
456 {
457 logger.error("XMLUtils:getElementTextFromString: Unable to find </" + start + ">.");
458 return null;
459 }
460
461 String val = docString.substring(begin + tmp.length(), end);
462 return val;
463 }
464
465
466
467
468
469
470
471
472
473
474
475 @SuppressWarnings("unused")
476 private static String getRootAttribute(InputStream inputStream, String attribute) throws JDOMException, IOException, Exception
477 {
478 Document doc = null;
479 doc = createDocumentFromStream(inputStream);
480 if (doc == null)
481 {
482 logger.error("XMLUtils: " + " getRootAttribute failed. Null document.");
483 throw new Exception("XMLUtils: getRootAttribute. Unable to create Document from stream.");
484 }
485 Element root = doc.getRootElement();
486 String attrVal = root.getAttributeValue(attribute);
487 return attrVal;
488 }
489
490
491
492
493
494
495
496
497
498
499
500
501
502 private static String getRootAttribute(Document xmlDoc, String attributeName) throws JDOMException, IOException, Exception
503 {
504 if (xmlDoc == null)
505 {
506 logger.error("XMLUtils: getRootAttribute failed. Null document.");
507 throw new Exception("XMLUtils: getRootAttribute. Unable to get attribute. Null Document.");
508 }
509 Element root = xmlDoc.getRootElement();
510 String attrVal = root.getAttributeValue(attributeName);
511 return attrVal;
512 }
513
514
515
516
517
518
519
520
521
522
523
524
525
526 @SuppressWarnings("unused")
527 private static String getRootAttributeFromString(String xml, String attributeName) throws JDOMException, IOException, Exception
528 {
529 Document xmlDoc = createDocumentFromString(xml);
530 if (xmlDoc == null)
531 {
532 logger.error("XMLUtils: getRootAttributeFromString failed. Null document.");
533 throw new Exception("XMLUtils: getRootAttributeFromString. Unable to get attribute. Null Document.");
534 }
535 return getRootAttribute(xmlDoc, attributeName);
536 }
537
538
539
540
541
542
543 public static String getXMLStringFromDoc(Document doc)
544 {
545 String resultingXML = null;
546 Format format = Format.getPrettyFormat();
547 format.setEncoding(DEFAULT_ENCODING);
548 XMLOutputter xmlOut = new XMLOutputter(format);
549 resultingXML = xmlOut.outputString(doc);
550 return resultingXML;
551 }
552
553
554
555
556
557
558
559
560 public static String prettyPrint(String xml) throws Exception
561 {
562 Document doc = createDocumentFromString(xml);
563 return getXMLStringFromDoc(doc);
564 }
565
566
567
568
569
570
571
572 public static Element getXPathElementFromString(String xmlString, String xPath) throws Exception
573 {
574 Document xmlDoc = createDocumentFromString(xmlString);
575 return getXPathElementFromDoc(xmlDoc, xPath);
576 }
577
578
579
580
581
582
583
584 public static String getXPathElementTextFromString(String xmlString, String xPath) throws Exception
585 {
586 Document xmlDoc = createDocumentFromString(xmlString);
587 Element elem = getXPathElementFromDoc(xmlDoc, xPath);
588 if (elem != null)
589 return elem.getText();
590 else return null;
591 }
592
593
594
595
596
597
598
599 public static String getXPathElementTextFromDoc(Document doc, String xPath) throws Exception
600 {
601 Element elem = getXPathElementFromDoc(doc, xPath);
602 if (elem != null)
603 return elem.getText();
604 else return null;
605 }
606
607
608
609
610
611
612
613 public static String getXPathAttributeTextFromString(String xmlString, String xPath) throws Exception
614 {
615 Document xmlDoc = createDocumentFromString(xmlString);
616 Attribute att = getXPathAttributeFromDoc(xmlDoc, xPath);
617 if (att != null)
618 return att.getValue();
619 else return null;
620 }
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636 public static Element getXPathElementFromDoc(Document xmlDoc, String xPath) throws Exception
637 {
638 XPath xpath1;
639 if (xmlDoc == null)
640 {
641 throw new Exception("getXPathElementFromDoc. Null document passed.");
642 }
643
644 if (isSet(xPath) && xPath.endsWith("/"))
645 {
646 xPath = xPath.substring(0, xPath.lastIndexOf("/"));
647 }
648
649 xpath1 = XPath.newInstance(xPath);
650 return (Element) xpath1.selectSingleNode(xmlDoc);
651 }
652
653 public static Attribute getXPathAttributeFromDoc(Document xmlDoc, String xPath) throws Exception
654 {
655 XPath xpath1;
656 if (xmlDoc == null)
657 {
658 throw new Exception("getXPathElementFromDoc. Null document passed.");
659 }
660
661 if (isSet(xPath) && xPath.endsWith("/"))
662 {
663 xPath = xPath.substring(0, xPath.lastIndexOf("/"));
664 }
665
666 xpath1 = XPath.newInstance(xPath);
667 return (Attribute) xpath1.selectSingleNode(xmlDoc);
668 }
669
670
671
672
673
674
675
676
677
678
679 @SuppressWarnings("unchecked")
680 public static List<Element> getXPathElementListFromDoc(Document xmlDoc, String xPathExpression) throws Exception
681 {
682 XPath xpath;
683 if (xmlDoc == null)
684 {
685 throw new Exception("getXPathElementFromDoc. Null document passed.");
686 }
687
688 if (isSet(xPathExpression) && xPathExpression.endsWith("/"))
689 {
690 xPathExpression = xPathExpression.substring(0, xPathExpression.lastIndexOf("/"));
691 }
692
693 xpath = XPath.newInstance(xPathExpression);
694 return xpath.selectNodes(xmlDoc);
695 }
696
697 public static List<Element> getXPathElementListFromString(String xmlString, String xPathExpression) throws Exception
698 {
699 Document doc = createDocumentFromString(xmlString);
700 return getXPathElementListFromDoc(doc, xPathExpression);
701 }
702
703
704
705
706
707
708
709
710
711
712
713 public static String getXPathValueFromString(String xmlString, String xPath)
714 {
715 try
716 {
717 Document doc = createDocumentFromString(xmlString);
718 return getXPathValueFromDoc(doc, xPath);
719 }
720 catch (Exception e)
721 {
722 return null;
723 }
724 }
725
726
727
728
729
730
731
732
733
734
735
736
737 public static String getXPathValueFromDoc(Document xmlDoc, String xPath) throws Exception
738 {
739 Element e;
740 String xmlValue = null;
741 XPathExpression xpe;
742 if (xmlDoc == null)
743 {
744 throw new Exception("XMLUtils:getXPathValueFromDoc. Null document passed.");
745 }
746
747 if (isSet(xPath) && xPath.endsWith("/"))
748 {
749 xPath = xPath.substring(0, xPath.lastIndexOf("/"));
750 }
751
752 xpe = xPathInstance.compile(xPath);
753 e = (Element) xpe.evaluate(xmlDoc, XPathConstants.NODE);
754 if (e != null)
755 {
756 if (e.getTextTrim() != null)
757 {
758 xmlValue = e.getTextTrim();
759 }
760 }
761 else
762 {
763 logger.error("XMLUtils:getXPathValueFromDoc. No value found for " + xPath + ".");
764 return null;
765 }
766 return xmlValue;
767 }
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784 public static String getXPathValueFromStream(InputStream inputStream, String xPath) throws Exception
785 {
786 Document doc = createDocumentFromStream(inputStream);
787 return getXPathValueFromDoc(doc, xPath);
788 }
789
790
791
792
793
794
795
796 public static void writeMetadataToLog(Document xmlDoc)
797 {
798 try
799 {
800 Format format = Format.getPrettyFormat();
801 format.setEncoding(DEFAULT_ENCODING);
802 XMLOutputter xmlOut = new XMLOutputter(format);
803 logger.debug("\n" + xmlOut.outputString(xmlDoc));
804 }
805 catch (Exception e)
806 {
807 logger.error("IOException in XMLUtils: writeMetadataToLog with document. No action taken", e);
808 }
809 }
810
811
812
813
814
815
816
817 public static void writeMetadataToLog(InputStream inputStream)
818 {
819 if (logger.isDebugEnabled())
820 {
821 try
822 {
823 Document doc = createDocumentFromStream(inputStream);
824 Format format = Format.getPrettyFormat();
825 format.setEncoding(DEFAULT_ENCODING);
826 XMLOutputter xmlOut = new XMLOutputter(format);
827 xmlOut.outputString(doc);
828 }
829 catch (Exception ex)
830 {
831 logger.error("Exception in XMLUtils with document. No action taken", ex);
832 }
833 finally
834 {
835 try
836 {
837 inputStream.close();
838 }
839 catch (IOException ioex)
840 {
841 logger.error("Unable to close stream. No action taken.");
842 }
843 }
844 }
845 }
846
847
848
849
850
851
852
853
854
855
856
857
858 public static void writeMetadataToOutputStream(Document newDoc, OutputStream metadataOutputStream)
859 {
860 try
861 {
862 Format format = Format.getPrettyFormat();
863 format.setEncoding(DEFAULT_ENCODING);
864 XMLOutputter xmlOut = new XMLOutputter(format);
865 xmlOut.output(newDoc, metadataOutputStream);
866 }
867 catch (IOException ioex)
868 {
869 logger.error("IOException in XMLUtils: No action taken.", ioex);
870 }
871 }
872
873 }