View Javadoc
1   /**
2   The contents of this file are subject to the Mozilla Public License Version 1.1 
3   (the "License"); you may not use this file except in compliance with the License. 
4   You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
5   Software distributed under the License is distributed on an "AS IS" basis, 
6   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
7   specific language governing rights and limitations under the License. 
8   
9   The Original Code is "XMLUtils.java".  Description: 
10  "XML utilities" 
11  
12  The Initial Developer of the Original Code is University Health Network. Copyright (C) 
13  2001.  All Rights Reserved. 
14  
15  Contributor(s): ______________________________________. 
16  
17  Alternatively, the contents of this file may be used under the terms of the 
18  GNU General Public License (the  "GPL"), in which case the provisions of the GPL are 
19  applicable instead of those above.  If you wish to allow use of your version of this 
20  file only under the terms of the GPL and not to allow others to use your version 
21  of this file under the MPL, indicate your decision by deleting  the provisions above 
22  and replace  them with the notice and other provisions required by the GPL License.  
23  If you do not delete the provisions above, a recipient may use your version of 
24  this file under either the MPL or the GPL. 
25   */
26  package ca.uhn.hl7v2.util;
27  
28  import java.io.*;
29  
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  import org.w3c.dom.DOMConfiguration;
33  import org.w3c.dom.DOMErrorHandler;
34  import org.w3c.dom.DOMImplementation;
35  import org.w3c.dom.Document;
36  import org.w3c.dom.bootstrap.DOMImplementationRegistry;
37  import org.w3c.dom.ls.DOMImplementationLS;
38  import org.w3c.dom.ls.LSInput;
39  import org.w3c.dom.ls.LSOutput;
40  import org.w3c.dom.ls.LSResourceResolver;
41  import org.w3c.dom.ls.LSSerializer;
42  import org.xml.sax.InputSource;
43  import org.xml.sax.SAXException;
44  
45  import javax.xml.parsers.DocumentBuilder;
46  import javax.xml.parsers.DocumentBuilderFactory;
47  import javax.xml.parsers.ParserConfigurationException;
48  
49  public class XMLUtils {
50      private static final Logger ourLog = LoggerFactory.getLogger(XMLUtils.class);
51  
52      private static DOMImplementation IMPL;
53  
54      @SuppressWarnings("unchecked")
55      public synchronized static <T> T getDOMImpl() {
56          if (IMPL == null) {
57              try {
58                  DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
59                  IMPL = registry.getDOMImplementation("LS 3.0");
60              } catch (Exception e) {
61                  throw new RuntimeException(e);
62              }
63          }
64          return (T) IMPL;
65      }
66  
67      @SuppressWarnings("unchecked")
68      public static Document parse(String s) {
69          return parseDocument(new InputSource(new StringReader(s)), false);
70      }
71  
72      public static Document parse(String s, boolean validateIfSchema) {
73          return parseDocument(new InputSource(new StringReader(s)), validateIfSchema);
74      }
75  
76      public static Document parse(InputStream s, boolean validateIfSchema) {
77          return parseDocument(new InputSource(s), validateIfSchema);
78      }
79  
80      public static Document parseDocument(InputSource theInputSource, boolean theValidating) {
81          DocumentBuilder builder;
82          try {
83              DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
84              docBuilderFactory.setNamespaceAware(true);
85              docBuilderFactory.setXIncludeAware(false);
86              docBuilderFactory.setExpandEntityReferences(false);
87              docBuilderFactory.setValidating(theValidating);
88              try {
89                  docBuilderFactory.setFeature(
90                          "http://apache.org/xml/features/disallow-doctype-decl", false);
91                  docBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
92                  docBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
93                  docBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
94                  docBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
95              } catch (Exception e) {
96                  ourLog.warn("Failed to set feature on XML parser: " + e.toString());
97              }
98  
99              builder = docBuilderFactory.newDocumentBuilder();
100         } catch (ParserConfigurationException e) {
101             throw new RuntimeException(e);
102         }
103 
104         try {
105             return builder.parse(theInputSource);
106         } catch (SAXException | IOException e) {
107             throw new RuntimeException(e);
108         }
109     }
110 
111 
112     public static void validate(Document d, String schema, DOMErrorHandler handler) {
113         DOMConfiguration config = d.getDomConfig();
114         config.setParameter("schema-type", "http://www.w3.org/2001/XMLSchema");
115         config.setParameter("validate", true);
116         config.setParameter("schema-location", schema);
117         config.setParameter("resource-resolver", new ClasspathResourceResolver());
118         config.setParameter("error-handler", handler);
119         d.normalizeDocument();
120     }
121 
122     public static String serialize(Document document, boolean prettyPrint) {
123         DOMImplementationLS impl = getDOMImpl();
124         LSSerializer serializer = impl.createLSSerializer();
125         // document.normalizeDocument();
126         DOMConfiguration config = serializer.getDomConfig();
127         if (prettyPrint && config.canSetParameter("format-pretty-print", Boolean.TRUE)) {
128             config.setParameter("format-pretty-print", true);
129         }
130         config.setParameter("xml-declaration", true);        
131         LSOutput output = impl.createLSOutput();
132         output.setEncoding("UTF-8");
133         Writer writer = new StringWriter();
134         output.setCharacterStream(writer);
135         serializer.write(document, output);
136         return writer.toString();
137     }
138 
139     public static Document emptyDocument(String title) {
140         DOMImplementation impl = getDOMImpl();
141         return impl.createDocument("urn:hl7-org:v2xml", title, null);
142     }
143 
144     /**
145      * This is an implementation of LSResourceResolver that can resolve XML schemas from the
146      * classpath
147      */
148     private static class ClasspathResourceResolver implements LSResourceResolver {
149         private final DOMImplementationLS impl;
150 
151         ClasspathResourceResolver() {
152             impl = getDOMImpl();
153         }
154 
155         public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId,
156                 String baseURI) {
157             LSInput lsInput = impl.createLSInput();
158             InputStream is = getClass().getResourceAsStream("/" + systemId);
159             if (is == null)
160                 return null;
161             lsInput.setByteStream(is);
162             return lsInput;
163         }
164     }
165 
166 }