Java Code Examples for javax.xml.parsers.DocumentBuilderFactory#setXIncludeAware()

The following examples show how to use javax.xml.parsers.DocumentBuilderFactory#setXIncludeAware() . These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may want to check out the right sidebar which shows the related API usage.
Example 1
/**
 * Test if two non nested xi:include elements can include the same document
 * with an xi:include statement.
 *
 * @throws Exception If any errors occur.
 */
@Test(groups = {"readWriteLocalFiles"})
public void testXIncludeNestedPos() throws Exception {
    String resultFile = USER_DIR + "schedule.out";
    String goldFile = GOLDEN_DIR + "scheduleGold.xml";
    String xmlFile = XML_DIR + "schedule.xml";

    try (FileOutputStream fos = new FileOutputStream(resultFile)) {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setXIncludeAware(true);
        dbf.setNamespaceAware(true);

        Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile));
        doc.setXmlStandalone(true);
        TransformerFactory.newInstance().newTransformer()
                .transform(new DOMSource(doc), new StreamResult(fos));
    }
    assertTrue(compareDocumentWithGold(goldFile, resultFile));
}
 
Example 2
Source Project: onos   File: XmlConfigParser.java    License: Apache License 2.0 6 votes vote down vote up
public static HierarchicalConfiguration loadXml(InputStream xmlStream) {
    try {
        XMLConfiguration cfg = new XMLConfiguration();
        DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
        //Disabling DTDs in order to avoid XXE xml-based attacks.
        disableFeature(dbfactory, DISALLOW_DTD_FEATURE);
        disableFeature(dbfactory, DISALLOW_EXTERNAL_DTD);
        dbfactory.setXIncludeAware(false);
        dbfactory.setExpandEntityReferences(false);
        cfg.setDocumentBuilder(dbfactory.newDocumentBuilder());
        cfg.load(xmlStream);
        return cfg;
    } catch (ConfigurationException | ParserConfigurationException e) {
        throw new IllegalArgumentException("Cannot load xml from Stream", e);
    }
}
 
Example 3
Source Project: hadoop   File: QueueConfigurationParser.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Method to load the resource file.
 * generates the root.
 * 
 * @param resourceInput InputStream that provides the XML to parse
 * @return
 * @throws ParserConfigurationException
 * @throws SAXException
 * @throws IOException
 */
protected Queue loadResource(InputStream resourceInput)
  throws ParserConfigurationException, SAXException, IOException {
  DocumentBuilderFactory docBuilderFactory
    = DocumentBuilderFactory.newInstance();
  //ignore all comments inside the xml file
  docBuilderFactory.setIgnoringComments(true);

  //allow includes in the xml file
  docBuilderFactory.setNamespaceAware(true);
  try {
    docBuilderFactory.setXIncludeAware(true);
  } catch (UnsupportedOperationException e) {
    LOG.info(
      "Failed to set setXIncludeAware(true) for parser "
        + docBuilderFactory
        + NAME_SEPARATOR + e);
  }
  DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
  Document doc = null;
  Element queuesNode = null;

  doc = builder.parse(resourceInput);
  queuesNode = doc.getDocumentElement();
  return this.parseResource(queuesNode);
}
 
Example 4
Source Project: lucene-solr   File: SafeXMLParsing.java    License: Apache License 2.0 6 votes vote down vote up
/** Parses a config file from ResourceLoader. Xinclude and external entities are enabled, but cannot escape the resource loader. */
public static Document parseConfigXML(Logger log, ResourceLoader loader, String file) throws SAXException, IOException {
  try (InputStream in = loader.openResource(file)) {
    final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setValidating(false);
    dbf.setNamespaceAware(true);
    trySetDOMFeature(dbf, XMLConstants.FEATURE_SECURE_PROCESSING, true);
    try {
      dbf.setXIncludeAware(true);
    } catch (UnsupportedOperationException e) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "XML parser doesn't support XInclude option", e);
    }
    
    final DocumentBuilder db = dbf.newDocumentBuilder();
    db.setEntityResolver(new SystemIdResolver(loader));
    db.setErrorHandler(new XMLErrorLogger(log));
    return db.parse(in, SystemIdResolver.createSystemIdFromResourceName(file));
  } catch (ParserConfigurationException pce) {
    throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "XML parser cannot be configured", pce);
  }
}
 
Example 5
Source Project: balana   File: Utils.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Create DocumentBuilderFactory with the XXE prevention measurements
 *
 * @return DocumentBuilderFactory instance
 */
public static DocumentBuilderFactory getSecuredDocumentBuilderFactory() {

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    dbf.setXIncludeAware(false);
    dbf.setExpandEntityReferences(false);
    try {
        dbf.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE, false);
        dbf.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE, false);
        dbf.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE, false);
        dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
    } catch (ParserConfigurationException e) {
        logger.error(
                "Failed to load XML Processor Feature " + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE + " or " +
                        Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE + " or " + Constants.LOAD_EXTERNAL_DTD_FEATURE);
    }

    SecurityManager securityManager = new SecurityManager();
    securityManager.setEntityExpansionLimit(ENTITY_EXPANSION_LIMIT);
    dbf.setAttribute(Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY, securityManager);

    return dbf;
}
 
Example 6
Source Project: cs-actions   File: XmlUtils.java    License: Apache License 2.0 6 votes vote down vote up
public static DocumentBuilder getDocumentBuilder(boolean secure) throws ParserConfigurationException {
    String feature;
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

    feature = "http://xml.org/sax/features/external-general-entities";
    factory.setFeature(feature, false);
    feature = "http://xml.org/sax/features/external-parameter-entities";
    factory.setFeature(feature, false);
    feature = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
    factory.setFeature(feature, false);
    feature = "http://apache.org/xml/features/disallow-doctype-decl";
    factory.setFeature(feature, true);
    factory.setXIncludeAware(false);
    factory.setExpandEntityReferences(false);
    factory.setNamespaceAware(true);
    factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, secure);
    return factory.newDocumentBuilder();
}
 
Example 7
Source Project: nutzwx   File: Wxs.java    License: Apache License 2.0 6 votes vote down vote up
public static DocumentBuilder xmls()
        throws ParserConfigurationException, SAXException, IOException {
    // 修复XXE form
    // https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_5
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    String FEATURE = null;
    FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
    factory.setFeature(FEATURE, true);
    FEATURE = "http://xml.org/sax/features/external-general-entities";
    factory.setFeature(FEATURE, false);
    FEATURE = "http://xml.org/sax/features/external-parameter-entities";
    factory.setFeature(FEATURE, false);
    FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
    factory.setFeature(FEATURE, false);
    factory.setXIncludeAware(false);
    factory.setExpandEntityReferences(false);
    return factory.newDocumentBuilder();
}
 
Example 8
/**
 * Creates a DocumentBuilder safe from XML external entities
 * attacks, and XML entity expansion attacks.
 * @return A DocumentBuilder safe to use to read untrusted XML.
 */
public static DocumentBuilder newSafeDocumentBuilder() throws ParserConfigurationException {
	DocumentBuilderFactory dbf = DOCUMENT_BUILDER_FACTORY;
	if (null == dbf) {
		// At worst we may do this twice if multiple threads
		// hit this method. It is Ok to have more than one
		// instance of the builder factory, as long as it is
		// XXE safe.
		dbf = DocumentBuilderFactory.newInstance();

		//
		// Adapted from: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#JAXP_DocumentBuilderFactory.2C_SAXParserFactory_and_DOM4J
		//
		// "...The JAXP DocumentBuilderFactory setFeature method allows a
		// developer to control which implementation-specific XML processor
		// features are enabled or disabled. The features can either be set
		// on the factory or the underlying XMLReader setFeature method. 
		// Each XML processor implementation has its own features that 
		// govern how DTDs and external entities are processed."
		//
		// "[disable] these as well, per Timothy Morgan's 2014 paper: 'XML 
		// Schema, DTD, and Entity Attacks'"
		dbf.setXIncludeAware(false);
		dbf.setExpandEntityReferences(false);

		// "This is the PRIMARY defense. If DTDs (doctypes) are disallowed,
		// almost all XML entity attacks are prevented"
		String FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
		dbf.setFeature(FEATURE, true);

		DOCUMENT_BUILDER_FACTORY = dbf;
	}

	return dbf.newDocumentBuilder();
}
 
Example 9
/**
 * This implementation allow DTD but disable all its dangerous features.
 * Not sure it can still do something useful with DTD ...
 */
public static void safeManualConfiguration() throws ParserConfigurationException, IOException, SAXException {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setFeature("http://xml.org/sax/features/external-general-entities",true);
    dbf.setFeature("http://xml.org/sax/features/external-parameter-entities",true);
    dbf.setXIncludeAware(false);
    dbf.setExpandEntityReferences(false);
    DocumentBuilder db = dbf.newDocumentBuilder();

    Document doc = db.parse(getInputFile());
    print(doc);
}
 
Example 10
public static Element stringToElement(String xml) {
	if (xml == null || xml.trim().length() == 0) {
		return null;
	}
	try {
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		docFactory.setNamespaceAware(false);
		docFactory.setXIncludeAware(false);
		docFactory.setExpandEntityReferences(false);

		docFactory.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE, false);

		docFactory.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE, false);

		docFactory.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE, false);

		SecurityManager securityManager = new SecurityManager();
		securityManager.setEntityExpansionLimit(0);
		docFactory.setAttribute(Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY,
				securityManager);

		DocumentBuilder db = docFactory.newDocumentBuilder();
		return db.parse(new ByteArrayInputStream(xml.getBytes())).getDocumentElement();
	} catch (Exception e) {
		throw new RuntimeException(e.getMessage(), e);
	}
}
 
Example 11
Source Project: MicroCommunity   File: PayUtil.java    License: Apache License 2.0 5 votes vote down vote up
/**
     * Map转换为 Xml
     *
     * @param map
     * @return Xml
     * @throws Exception
     */
    public static String mapToXml(SortedMap<String, String> map) throws Exception {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//防止XXE攻击
        documentBuilderFactory.setXIncludeAware(false);
        documentBuilderFactory.setExpandEntityReferences(false);
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = documentBuilder.newDocument();
        org.w3c.dom.Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key : map.keySet()) {
            String value = map.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString();
        try {
            writer.close();
        } catch (Exception ex) {
        }
        return output;
    }
 
Example 12
public static void unsafeManualConfig4() throws ParserConfigurationException, IOException, SAXException {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setFeature("http://xml.org/sax/features/external-general-entities",true);
    dbf.setFeature("http://xml.org/sax/features/external-parameter-entities",true);
    dbf.setXIncludeAware(false);
    //dbf.setExpandEntityReferences(false);
    DocumentBuilder db = dbf.newDocumentBuilder();

    Document doc = db.parse(getInputFile());
    print(doc);
}
 
Example 13
Source Project: vespa   File: Xml.java    License: Apache License 2.0 5 votes vote down vote up
static DocumentBuilder getPreprocessDocumentBuilder() throws ParserConfigurationException {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setFeature("http://xml.org/sax/features/external-general-entities", false); // XXE prevention
    factory.setNamespaceAware(true);
    factory.setXIncludeAware(false);
    factory.setValidating(false);
    return factory.newDocumentBuilder();
}
 
Example 14
private static Document loadXml(InputStream fn) throws Exception {
  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
    factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
    factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
    factory.setXIncludeAware(false);
    factory.setExpandEntityReferences(false);
      
  factory.setNamespaceAware(true);
    DocumentBuilder builder = factory.newDocumentBuilder();
    return builder.parse(fn);
}
 
Example 15
private static Document loadXml(InputStream fn) throws Exception {
  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
    factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
    factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
    factory.setXIncludeAware(false);
    factory.setExpandEntityReferences(false);
      
  factory.setNamespaceAware(true);
    DocumentBuilder builder = factory.newDocumentBuilder();
    return builder.parse(fn);
}
 
Example 16
Source Project: NutzSite   File: WXPayXmlUtil.java    License: Apache License 2.0 5 votes vote down vote up
public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
    documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
    documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
    documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
    documentBuilderFactory.setXIncludeAware(false);
    documentBuilderFactory.setExpandEntityReferences(false);

    return documentBuilderFactory.newDocumentBuilder();
}
 
Example 17
private String getProfileId(String protocol) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
  factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
  factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
  factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
  factory.setXIncludeAware(false);
  factory.setExpandEntityReferences(false);
  factory.setNamespaceAware(true);
  DocumentBuilder builder = factory.newDocumentBuilder();
  Document doc = builder.parse(new InputSource(new StringReader(protocol)));
  
  XPath xPath = XPathFactory.newInstance().newXPath();
  return (String)xPath.evaluate("/protocol[@type='CSW']/profile", doc, XPathConstants.STRING);
}
 
Example 18
/**
 * Loads profiles.
 * @return profiles
 * @throws IOException if loading profiles from configuration fails
 * @throws ParserConfigurationException if unable to obtain XML parser
 * @throws SAXException if unable to parse XML document
 * @throws XPathExpressionException if invalid XPath expression
 */
public Profiles load() throws IOException, ParserConfigurationException, SAXException, XPathExpressionException {
  LOG.info(String.format("Loading CSW profiles"));
  Profiles profiles = new Profiles();
  try (InputStream profilesXml = Thread.currentThread().getContextClassLoader().getResourceAsStream(CONFIG_FILE_PATH);) {
    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    builderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
    builderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
    builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
    builderFactory.setXIncludeAware(false);
    builderFactory.setExpandEntityReferences(false);
    builderFactory.setNamespaceAware(true);
    DocumentBuilder builder = builderFactory.newDocumentBuilder();
    
    Document profilesDom = builder.parse(new InputSource(profilesXml));
    
    XPathFactory xPathfactory = XPathFactory.newInstance();
    XPath xpath = xPathfactory.newXPath();  
    
    NodeList profilesNodeList = (NodeList) xpath.evaluate("/CSWProfiles/Profile", profilesDom, XPathConstants.NODESET);
    for (int pidx = 0; pidx<profilesNodeList.getLength(); pidx++) {
      Node profileNode = profilesNodeList.item(pidx);
      String id = StringUtils.trimToEmpty((String)xpath.evaluate("ID", profileNode, XPathConstants.STRING));
      String name = StringUtils.trimToEmpty((String)xpath.evaluate("Name", profileNode, XPathConstants.STRING));
      String namespace = StringUtils.trimToEmpty((String)xpath.evaluate("CswNamespace", profileNode, XPathConstants.STRING));
      String description = StringUtils.trimToEmpty((String)xpath.evaluate("Description", profileNode, XPathConstants.STRING));
      
      String expectedGptXmlOutput = StringUtils.trimToEmpty((String)xpath.evaluate("GetRecords/@expectedGptXmlOutput", profileNode, XPathConstants.STRING));
      String getRecordsReqXslt = StringUtils.trimToEmpty((String)xpath.evaluate("GetRecords/XSLTransformations/Request", profileNode, XPathConstants.STRING));
      String getRecordsRspXslt = StringUtils.trimToEmpty((String)xpath.evaluate("GetRecords/XSLTransformations/Response", profileNode, XPathConstants.STRING));
      
      String getRecordByIdReqKVP = StringUtils.trimToEmpty((String)xpath.evaluate("GetRecordByID/RequestKVPs", profileNode, XPathConstants.STRING));
      String getRecordByIdRspXslt = StringUtils.trimToEmpty((String)xpath.evaluate("GetRecordByID/XSLTransformations/Response", profileNode, XPathConstants.STRING));
      
      Profile prof = new Profile();
      prof.setId(id);
      prof.setName(name);
      prof.setDescription(description);
      prof.setExpectedGptXmlOutput(expectedGptXmlOutput);
      prof.setGetRecordsReqXslt(getRecordsReqXslt);
      prof.setGetRecordsRspXslt(getRecordsRspXslt);
      prof.setKvp(getRecordByIdReqKVP);
      prof.setGetRecordByIdRspXslt(getRecordByIdRspXslt);
      
      profiles.add(prof);
    }
  }
  LOG.info(String.format("CSW profiles loaded."));
  return profiles;
}
 
Example 19
Source Project: org.hl7.fhir.core   File: XmlParser.java    License: Apache License 2.0 4 votes vote down vote up
public Element parse(InputStream stream) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
Document doc = null;
	try {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		// xxe protection
		factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
		factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
		factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
		factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
		factory.setXIncludeAware(false);
		factory.setExpandEntityReferences(false);
			
		factory.setNamespaceAware(true);
		if (policy == ValidationPolicy.EVERYTHING) {
			// use a slower parser that keeps location data
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer nullTransformer = transformerFactory.newTransformer();
			DocumentBuilder docBuilder = factory.newDocumentBuilder();
			doc = docBuilder.newDocument();
			DOMResult domResult = new DOMResult(doc);
			SAXParserFactory spf = SAXParserFactory.newInstance();
			spf.setNamespaceAware(true);
			spf.setValidating(false);
  		// xxe protection
		  spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
      spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
			SAXParser saxParser = spf.newSAXParser();
			XMLReader xmlReader = saxParser.getXMLReader();
  		// xxe protection
		  xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
		  xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
	   			
			XmlLocationAnnotator locationAnnotator = new XmlLocationAnnotator(xmlReader, doc);
			InputSource inputSource = new InputSource(stream);
			SAXSource saxSource = new SAXSource(locationAnnotator, inputSource);
			nullTransformer.transform(saxSource, domResult);
		} else {
			DocumentBuilder builder = factory.newDocumentBuilder();
			doc = builder.parse(stream);
		}
	} catch (Exception e) {
    logError(0, 0, "(syntax)", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL);
    doc = null;
	}
	if (doc == null)
		return null;
	else
    return parse(doc);
}
 
Example 20
/**
 * Reads record from the stream
 *
 * @param contentStream content stream
 * @return list of records
 * @throws IOException if reading records fails
 * @throws TransformerConfigurationException if creating transformer fails
 * @throws TransformerException if creating transformer fails
 * @throws ParserConfigurationException if unable to create XML parser
 * @throws SAXException if unable to parse content
 * @throws XPathExpressionException if invalid XPath
 */
private List<IRecord> readRecords(InputStream contentStream) throws IOException, TransformerConfigurationException, TransformerException, ParserConfigurationException, SAXException, XPathExpressionException {
  ArrayList<IRecord> records = new ArrayList<>();

  // create transformer
  Templates template = TemplatesManager.getInstance().getTemplate(profile.getResponsexslt());
  Transformer transformer = template.newTransformer();

  // perform transformation
  StringWriter writer = new StringWriter();
  transformer.transform(new StreamSource(contentStream), new StreamResult(writer));
  
  LOG.trace(String.format("Received records:\n%s", writer.toString()));

  try (ByteArrayInputStream transformedContentStream = new ByteArrayInputStream(writer.toString().getBytes("UTF-8"))) {

    // create internal request DOM
    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    builderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
    builderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
    builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
    builderFactory.setXIncludeAware(false);
    builderFactory.setExpandEntityReferences(false);
    DocumentBuilder builder = builderFactory.newDocumentBuilder();
    Document resultDom = builder.parse(new InputSource(transformedContentStream));

    // create xpath
    XPathFactory xPathfactory = XPathFactory.newInstance();
    XPath xpath = xPathfactory.newXPath();

    NodeList recordNodeList = (NodeList) xpath.evaluate("/Records/Record", resultDom, XPathConstants.NODESET);
    for (int i = 0; i < recordNodeList.getLength(); i++) {
      Node recordNode = recordNodeList.item(i);
      String id = (String) xpath.evaluate("ID", recordNode, XPathConstants.STRING);
      String strModifiedDate = (String) xpath.evaluate("ModifiedDate", recordNode, XPathConstants.STRING);
      Date modifedDate = parseIsoDate(strModifiedDate);
      IRecord record = new Record(id, modifedDate);
      records.add(record);
    }
  }

  return records;
}