--- /dev/null
+<report>
+ <recorded result="OK">
+ <program>
+ <name>Wintertijd</name>
+ <description>Some description MINSK - De presidentsverkiezingen in Wit-Rusland zijn zondag met ruime cijfers gewonnen door zittend president Aleksandr Loekasjenko. Dat bleek zondag uit exitpolls uitgevoerd in opdracht van het totalitaire regime. Het staatshoofd zou kunnen rekenen op ruim 82 procent van de stemmen. Volgens de eerste gedeeltelijke uitslagen zou Loekasjenko zelfs kunnen rekenen op bijna 89 procent. </description>
+ <keywords>Documentaire</keywords>
+ <channel>Nederland 1</channel>
+ <interval>
+ <begin>23:25</begin>
+ <end>00:10</end>
+ </interval>
+ </program>
+ </recorded>
+
+ <interesting>
+ <program>
+ <name>Brainiac</name>
+ <description>Humor</description>
+ <keywords>science</keywords>
+ <channel>Discovery Channel</channel>
+ <interval>
+ <begin>23:30</begin>
+ <end>00:15</end>
+ </interval>
+ </program>
+ <category name="horror">
+ <program>
+ <name>Andere tijden</name>
+ <description>Documentaire</description>
+ <keywords>docu</keywords>
+ <channel>Nederland 1</channel>
+ <interval>
+ <begin>23:30</begin>
+ <end>00:15</end>
+ </interval>
+ </program>
+ </category>
+
+ </interesting>
+
+</report>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:template match="report">
+ <html>
+ <head>
+ <title>KiSS crawler report</title>
+ </head>
+ <body>
+ <h1>KiSS crawler report</h1>
+ <xsl:apply-templates select="recorded"/>
+ <xsl:if test="count(interesting) > 0">
+ <h2>Possibly interesting programs</h2>
+ <xsl:apply-templates select="interesting"/>
+ </xsl:if>
+ <xsl:if test="count(//program) = 0">
+ <xsl:text>No suitable programs found </xsl:text>
+ </xsl:if>
+ </body>
+ </html>
+
+ </xsl:template>
+
+ <xsl:template name="programTable">
+ <p>
+ <table align="left" cellpadding="5">
+ <!--
+ <tr align="left">
+ <th align="left">Time</th>
+ <th align="left">Channel</th>
+ <th align="left">Program</th>
+ </tr>
+ -->
+ <xsl:apply-templates select="program"/>
+ </table>
+ <br clear="left"/>
+ </p>
+ </xsl:template>
+
+ <xsl:template match="recorded">
+ <h2>
+ <xsl:choose>
+ <xsl:when test="@result = 'OK'">
+ <xsl:text>Successfully recorded programs </xsl:text>
+ <xsl:call-template name="programTable"/>
+ </xsl:when>
+ <xsl:when test="@result = 'DUPLICATE'">
+ <xsl:text>Already recorded programs</xsl:text>
+ <xsl:call-template name="programTable"/>
+ </xsl:when>
+ <xsl:when test="@result = 'CONFLICT'">
+ <xsl:text>Conflicts with other recorded programs</xsl:text>
+ <xsl:call-template name="programTable"/>
+ </xsl:when>
+ <xsl:when test="@result='ERROR'">
+ <xsl:text>Programs that could not be recorded for
+ technical reasons.</xsl:text>
+ <xsl:call-template name="programTable"/>
+ </xsl:when>
+ </xsl:choose>
+ </h2>
+ </xsl:template>
+
+ <xsl:template name="addProgramInfo">
+ <tr align="left">
+ <td><xsl:value-of select="interval/begin"/> - <xsl:value-of select="interval/end"/>: <strong>
+ <xsl:value-of select="name"/>
+ </strong> (<xsl:value-of select="channel"/>/<xsl:value-of select="keywords"/>)</td>
+
+ </tr>
+ <tr>
+ <td>
+ <blockquote>
+ <font size="-1">
+ <xsl:value-of select="description"/>
+ </font>
+ </blockquote>
+ </td>
+
+
+ </tr>
+ </xsl:template>
+
+ <xsl:template match="program">
+ <xsl:call-template name="addProgramInfo"/>
+ </xsl:template>
+
+ <xsl:template match="interesting">
+ <xsl:call-template name="programTable"/>
+ <xsl:apply-templates select="category"/>
+ </xsl:template>
+
+ <xsl:template match="category">
+ <h3>Category: <xsl:value-of select="@name"/></h3>
+ <xsl:call-template name="programTable"/>
+ </xsl:template>
+</xsl:stylesheet>
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Note the declaration of the namespace for XInclude. -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+
+ <xsl:variable name="newline">
+ <xsl:text> </xsl:text>
+ </xsl:variable>
+
+ <xsl:variable name="carriageReturn">
+ <xsl:text> </xsl:text>
+ </xsl:variable>
+
+ <!-- =====================================================
+ Replace one string by another
+ - src: string to do substituion in
+ - from: literal string to replace
+ - to:substitution string.
+ ======================================================-->
+ <xsl:template name="string-replace">
+ <xsl:param name="src"/>
+ <xsl:param name="from"/>
+ <xsl:param name="to"/>
+ <xsl:choose>
+ <xsl:when test="contains($src, $from)">
+ <xsl:value-of select="substring-before($src, $from)"/>
+ <xsl:value-of select="$to"/>
+ <xsl:call-template name="string-replace">
+ <xsl:with-param name="src" select="substring-after($src, $from)"/>
+ <xsl:with-param name="from" select="$from"/>
+ <xsl:with-param name="to" select="$to"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$src"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="indent">
+ <xsl:param name="src"/>
+ <xsl:param name="indentString"/>
+ <xsl:value-of select="$indentString"/>
+ <xsl:call-template name="string-replace">
+ <xsl:with-param name="src">
+ <xsl:value-of select="$src"/>
+ </xsl:with-param>
+ <xsl:with-param name="from">
+ <xsl:value-of select="$newline"/>
+ </xsl:with-param>
+ <xsl:with-param name="to">
+ <xsl:value-of select="$newline"/>
+ <xsl:value-of select="$indentString"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template name="word-wrap">
+ <xsl:param name="src"/>
+ <xsl:param name="width"/>
+
+ <xsl:call-template name="word-wrap-impl">
+ <xsl:with-param name="src">
+ <xsl:call-template name="string-replace">
+ <xsl:with-param name="src">
+ <xsl:value-of select="$src"/>
+ </xsl:with-param>
+ <xsl:with-param name="from">
+ <xsl:text> </xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="to">
+ <xsl:text> </xsl:text>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="width">
+ <xsl:value-of select="$width"/>
+ </xsl:with-param>
+ <xsl:with-param name="index">
+ <xsl:value-of select="0"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template name="word-wrap-impl">
+ <xsl:param name="src"/>
+ <xsl:param name="index"/>
+ <xsl:param name="width"/>
+
+ <xsl:variable name="word">
+ <xsl:value-of select="substring-before($src, ' ')"/>
+ </xsl:variable>
+ <xsl:variable name="wordlength">
+ <xsl:value-of select="string-length($word)"/>
+ </xsl:variable>
+ <xsl:variable name="remainder">
+ <xsl:value-of select="substring($src, $wordlength+2)"/>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="$index + $wordlength + 1 > $width">
+ <xsl:value-of select="$newline"/>
+ <xsl:value-of select="$word"/>
+ <xsl:text> </xsl:text>
+ <xsl:if test="string-length($remainder) > 0">
+ <xsl:call-template name="word-wrap-impl">
+ <xsl:with-param name="src">
+ <xsl:value-of select="$remainder"/>
+ </xsl:with-param>
+ <xsl:with-param name="index">
+ <xsl:value-of select="$wordlength + 1"/>
+ </xsl:with-param>
+ <xsl:with-param name="width">
+ <xsl:value-of select="$width"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$word"/>
+ <xsl:text> </xsl:text>
+
+ <xsl:if test="string-length($remainder) > 0">
+ <xsl:call-template name="word-wrap-impl">
+ <xsl:with-param name="src">
+ <xsl:value-of select="$remainder"/>
+ </xsl:with-param>
+ <xsl:with-param name="index">
+ <xsl:value-of select="$index + $wordlength+1"/>
+ </xsl:with-param>
+ <xsl:with-param name="width">
+ <xsl:value-of select="$width"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
--- /dev/null
+/*
+ * Copyright 2005 the original author or authors.
+ *
+ * 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.wamblee.xml;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.dom4j.DocumentException;
+import org.dom4j.io.DOMReader;
+import org.dom4j.io.DOMWriter;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/**
+ * Some basic XML utilities for common reoccuring tasks for
+ * DOM documents.
+ */
+public final class DomUtils {
+
+ /**
+ * Disabled default constructor.
+ *
+ */
+ private DomUtils() {
+ // Empty.
+ }
+
+
+ /**
+ * Parses an XML document from a stream.
+ * @param aIs Input stream.
+ * @return
+ */
+ public static Document read(InputStream aIs) throws SAXException, ParserConfigurationException, IOException {
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ return builder.parse(aIs);
+ }
+
+ /**
+ * Serializes an XML document to a stream.
+ * @param aDocument Document to serialize.
+ * @param aOs Output stream.
+ */
+ public static void serialize(Document aDocument, OutputStream aOs) throws IOException {
+ XMLSerializer serializer = new XMLSerializer(aOs, new OutputFormat());
+ serializer.serialize(aDocument);
+ }
+
+ /**
+ * Serializes an XML document.
+ * @param aDocument Document to serialize.
+ * @return Serialized document.
+ */
+ public static String serialize(Document aDocument) throws IOException {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ serialize(aDocument, os);
+ return os.toString();
+ }
+
+ /**
+ * Converts a dom4j document into a w3c DOM document.
+ * @param aDocument Document to convert.
+ * @return W3C DOM document.
+ */
+ public static Document convert(org.dom4j.Document aDocument) throws DocumentException {
+ return new DOMWriter().write(aDocument);
+ }
+
+ /**
+ * Converts a W3C DOM document into a dom4j document.
+ * @param aDocument Document to convert.
+ * @return Dom4j document.
+ */
+ public static org.dom4j.Document convert(Document aDocument) {
+ return new DOMReader().read(aDocument);
+ }
+}
import java.io.IOException;
import java.io.InputStream;
-import org.wamblee.test.FileSystemUtils;
import junit.framework.TestCase;
import java.io.IOException;
import java.io.InputStream;
-import org.wamblee.test.FileSystemUtils;
import junit.framework.TestCase;
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.wamblee.test;
+package org.wamblee.io;
import java.io.File;
import java.io.IOException;
import java.io.IOException;
import java.io.InputStream;
-import org.wamblee.test.FileSystemUtils;
import junit.framework.TestCase;
package org.wamblee.io;
import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import org.wamblee.test.FileSystemUtils;
/**
* Test resource for locating resources in the classpath.
--- /dev/null
+/*
+ * Copyright 2005 the original author or authors.
+ *
+ * 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.wamblee.xml;
+
+import java.io.IOException;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.URIResolver;
+import javax.xml.transform.stream.StreamSource;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.io.ClassPathResource;
+import org.wamblee.io.FileSystemUtils;
+
+/**
+ * Tests for {@link org.wamblee.xml.ClasspathUriResolver}.
+ */
+public class ClasspathUriResolverTest extends TestCase {
+
+ private URIResolver _resolver;
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ _resolver = new ClasspathUriResolver();
+ }
+
+ /**
+ * Resolves an existing file. Verifies the file is resolved correctly.
+ * @throws TransformerException
+ * @throws IOException
+ */
+ public void testResolveExistingFile() throws TransformerException, IOException {
+ Source source = _resolver.resolve("org/wamblee/xml/reportToHtml.xsl", "");
+ assertTrue(source instanceof StreamSource);
+ String resolved = FileSystemUtils.read(((StreamSource)source).getInputStream());
+
+ ClassPathResource resource = new ClassPathResource("org/wamblee/xml/reportToHtml.xsl");
+ String expected = FileSystemUtils.read(resource.getInputStream());
+ assertEquals(expected, resolved);
+ }
+
+ /**
+ * Resolves a non-existing file. Verifies that a TransformerException is thrown.
+ *
+ */
+ public void testResolveNonExistingFile() {
+ try {
+ Source source = _resolver.resolve("org/wamblee/xml/reportToHtml-nonexisting.xsl", "");
+ } catch (TransformerException e) {
+ return; // ok
+ }
+ fail();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2005 the original author or authors.
+ *
+ * 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.wamblee.xml;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.dom4j.Attribute;
+import org.dom4j.Document;
+import org.dom4j.Element;
+
+
+
+/**
+ * XML test support utilities.
+ */
+public final class XmlUtils {
+
+ /**
+ * Disabled constructor.
+ *
+ */
+ private XmlUtils() {
+ // Empty
+ }
+
+ /**
+ * Checks equality of two XML documents excluding comment and processing nodes and
+ * trimming the text of the elements.
+ * @param aMsg
+ * @param aExpected
+ * @param aActual
+ */
+ public static void assertEquals(String aMsg, Document aExpected, Document aActual) {
+ assertEquals(aMsg, aExpected.getRootElement(), aActual.getRootElement());
+ }
+
+ /**
+ * Checks equality of two XML elements excluding comment and processing nodes and trimming
+ * the text of the elements.
+ * @param aMsg
+ * @param aExpected
+ * @param aActual
+ */
+ public static void assertEquals(String aMsg, Element aExpected, Element aActual) {
+
+ // Name.
+ TestCase.assertEquals(aMsg + "/name()", aExpected.getName(), aActual.getName());
+
+ // Text
+ TestCase.assertEquals(aMsg + "/text()", aExpected.getTextTrim(), aActual.getTextTrim());
+
+ // Attributes
+ List<Attribute> expectedAttrs = aExpected.attributes();
+ Collections.sort(expectedAttrs, new AttributeComparator());
+ List<Attribute> actualAttrs = aActual.attributes();
+ Collections.sort(actualAttrs, new AttributeComparator());
+
+ TestCase.assertEquals(aMsg + "/#attributes", expectedAttrs.size(), actualAttrs.size());
+ for (int i = 0; i < expectedAttrs.size(); i++) {
+ String msg = aMsg + "/attribute(" + i + ")";
+ assertEquals(msg, expectedAttrs.get(i), actualAttrs.get(i));
+ }
+
+ // Nested elements.
+ List<Element> expectedElems = aExpected.elements();
+ List<Element> actualElems = aActual.elements();
+ TestCase.assertEquals(aMsg + "/#elements", expectedElems.size(), actualElems.size());
+ for (int i = 0; i < expectedElems.size(); i++) {
+ String msg = aMsg + "/element(" + i + ")";
+ assertEquals(msg, expectedElems.get(i), actualElems.get(i));
+ }
+ }
+
+ /**
+ * Checks equality of two attributes.
+ * @param aMsg
+ * @param aExpected
+ * @param aActual
+ */
+ public static void assertEquals(String aMsg, Attribute aExpected, Attribute aActual) {
+ TestCase.assertEquals(aMsg + "@", aExpected.getName() + ":name", aActual.getName());
+ TestCase.assertEquals(aMsg + "@" + aExpected.getName() + ":value",
+ aExpected.getValue(), aActual.getValue());
+ }
+
+ /**
+ * Comparator which compares attributes by name.
+ */
+ private static final class AttributeComparator implements Comparator<Attribute> {
+ /* (non-Javadoc)
+ * @see java.util.Comparator#compare(T, T)
+ */
+ public int compare(Attribute aAttribute1, Attribute aAttribute2) {
+ return aAttribute1.getName().compareTo(aAttribute2.getName());
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2005 the original author or authors.
+ *
+ * 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.wamblee.xml;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import junit.framework.TestCase;
+
+import org.w3c.dom.Document;
+import org.wamblee.io.FileSystemUtils;
+import org.wamblee.io.InputResource;
+import org.wamblee.io.TestResource;
+
+/**
+ * Tests the XSL transformer.
+ */
+public class XslTransformerTest extends TestCase {
+
+ private static final String REPORT_XML = "report.xml";
+ private static final String REPORT_TO_HTML_XSLT = "reportToHtml.xsl";
+
+ /**
+ * Transforms a file while using the default resolver,
+ * where the included file can be found.
+ * Verifies the transformation is done correctly.
+ *
+ */
+ public void testTransformUsingDefaultResolver() throws Exception {
+ XslTransformer transformer = new XslTransformer();
+
+ InputResource xmlResource = new TestResource(XslTransformerTest.class, REPORT_XML);
+ Source xslt = new StreamSource(new File( FileSystemUtils.getTestInputDir(XslTransformerTest.class), REPORT_TO_HTML_XSLT));
+
+ byte[] documentData = FileSystemUtils.read(xmlResource.getInputStream()).getBytes();
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ Document document = builder.parse(xmlResource.getInputStream());
+ Source documentSource = new StreamSource(xmlResource.getInputStream());
+
+ Document output1 = transformer.transform(documentData, xslt);
+ Document output2 = transformer.transform(document, xslt);
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ Result output = new StreamResult(os);
+ transformer.transform(documentSource, output, xslt);
+ transformer.textTransform(documentData, xslt);
+ }
+
+ /**
+ * Transforms a file using the default resolver where the
+ * included file cannot be found.
+ * Verifies that a TransformerException is thrown.
+ *
+ */
+ public void testTransformUsingDefaultResolverFails() {
+ fail();
+ }
+
+ /**
+ * Transforms a file using an invalid Xslt.
+ * Verifies that a TransformerException is thrown.
+ *
+ */
+ public void testTransformInvalidXslt() {
+ fail();
+ }
+
+ /**
+ * Transforms a file using a non-well formed xslt.
+ * Verifies that a TransformerException is thrown.
+ *
+ */
+ public void testTransformNonWellformedXslt() {
+ fail();
+ }
+
+ /**
+ * Transforms a file using a class path resolver.
+ *
+ */
+ public void testTransformUsingClassPathResolver() {
+ fail();
+ }
+
+ /**
+ * Transforms a file to text output.
+ * Verifies the file is transformed correctly.
+ *
+ */
+ public void testTransformToTextOutput() {
+ fail();
+ }
+}