/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.esigate.xml; import java.io.IOException; import java.io.StringReader; import java.io.Writer; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import nu.validator.htmlparser.common.DoctypeExpectation; import nu.validator.htmlparser.dom.Dom2Sax; import nu.validator.htmlparser.dom.HtmlDocumentBuilder; import org.esigate.Renderer; import org.esigate.impl.DriverRequest; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * XML renderer. * <p> * Applies optional XPath evaluation and XSLT transformation to the retrieved data. * * @author Stanislav Bernatskyi */ public class XpathRenderer implements Renderer { private static final HtmlNamespaceContext HTML_NAMESPACE_CONTEXT = new HtmlNamespaceContext(); private static final XPathFactory X_PATH_FACTORY = XPathFactory.newInstance(); private final XPathExpression expr; public XpathRenderer(String xpath) { try { XPath xpathObj = X_PATH_FACTORY.newXPath(); xpathObj.setNamespaceContext(HTML_NAMESPACE_CONTEXT); this.expr = xpathObj.compile(xpath); } catch (XPathExpressionException e) { throw new ProcessingFailedException("failed to compile XPath expression", e); } } /** {@inheritDoc} */ @Override public void render(DriverRequest httpRequest, String src, Writer out) throws IOException { try { HtmlDocumentBuilder htmlDocumentBuilder = new HtmlDocumentBuilder(); htmlDocumentBuilder.setDoctypeExpectation(DoctypeExpectation.NO_DOCTYPE_ERRORS); Document document = htmlDocumentBuilder.parse(new InputSource(new StringReader(src))); NodeList matchingNodes = (NodeList) expr.evaluate(document, XPathConstants.NODESET); XhtmlSerializer serializer = new XhtmlSerializer(out); Dom2Sax dom2Sax = new Dom2Sax(serializer, serializer); for (int i = 0; i < matchingNodes.getLength(); i++) { dom2Sax.parse(matchingNodes.item(i)); } } catch (XPathExpressionException e) { throw new ProcessingFailedException("Failed to evaluate XPath expression", e); } catch (SAXException e) { throw new ProcessingFailedException("Unable to parse source", e); } } }