package com.googlecode.totallylazy.xml; import com.googlecode.totallylazy.Sequence; import com.googlecode.totallylazy.functions.TimeReport; import com.googlecode.totallylazy.matchers.NumberMatcher; import org.hamcrest.CoreMatchers; import org.junit.Ignore; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; import java.util.Iterator; import java.util.NoSuchElementException; import static com.googlecode.totallylazy.Sequences.repeat; import static com.googlecode.totallylazy.Sequences.sequence; import static com.googlecode.totallylazy.matchers.IterableMatcher.hasExactly; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.fail; public class XmlTest { @Test public void shouldSupportRealWorldNamespacesAndComplexQueries() throws Exception { Document bt = Xml.document("<?xml version=\"1.0\"?>\n" + "<or:OrderStatusUpdate xmlns:gea=\"urn:uk.org.telcob2b/tML/Fulfilment/GEA-v16-0\" xmlns:odr=\"urn:uk.org.telcob2b/tML/BT-OrderResponse-v16-0\" xmlns:or=\"urn:com.openreach.Fulfilment2-v16-0\" xmlns:utcc=\"urn:uk.org.telcob2b/tML/ukt-CommonComponents-v16-0\" xmlns=\"\">\n" + " <odr:OrderResponse>\n" + " <utcc:RespondedOrderLine>\n" + " <utcc:OrderLineMessageInfo>\n" + " <utcc:MessageInfo>\n" + " <utcc:CompletionCode>510</utcc:CompletionCode>\n" + " </utcc:MessageInfo>\n" + " </utcc:OrderLineMessageInfo>\n" + " </utcc:RespondedOrderLine>\n" + " </odr:OrderResponse>\n" + "</or:OrderStatusUpdate>\n"); assertThat(Xml.selectNodes(bt, "tl:trim-and-join(//MessageInfo/CompletionCode, \"\\n\")").size(), is(1)); } @Test @Ignore("manual test") public void xpathIsPrettyFast() throws Exception { final Document document = example(); TimeReport report = TimeReport.time(1000, () -> { return Xml.selectNodes(document, "//meta/@content"); }); System.out.println(report); } @Test public void canLoadHtml() throws Exception { Document document = example(); assertThat(Xml.selectNodes(document, "//meta/@content").map(Xml.contents()), hasExactly("Foo", "Bar")); assertThat(Xml.selectContents(document, "descendant::boo"), is("far")); assertThat(Xml.selectContents(document, "descendant::foo"), is("baz")); } private Document example() { return Xml.document( "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML+RDFa 1.0//EN\" \"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd\">\n" + "<xh:html xmlns:xh=\"http://www.w3.org/1999/xhtml\" xmlns:og=\"http://opengraphprotocol.org/schema/\" xml:lang=\"en-GB\" xmlns=\"\">\n" + "<xh:head><xh:meta content=\"Foo\"/><xh:meta content=\"Bar\"/></xh:head>" + "<foo>baz</foo>" + "<og:boo>far</og:boo>" + "</xh:html>"); } @Test public void canEscapeXml() throws Exception { assertThat(Xml.escape("& < > ' \" " + new Character((char) 0x80)), is("& < > ' " €")); } @Test public void doesNotTruncateString() throws Exception { String testString = longStringWithoutEncodedChars(); assertThat(Xml.escape(testString), is(testString)); } private String longStringWithoutEncodedChars() { return repeat("A").take(100).toString(""); } @Test public void supportsXPathExpressionsWithFunctionsThatReturnStrings() throws Exception{ Document document = Xml.document("<root><child type=\"name\" value=\"bob\"/></root>"); String value = Xml.selectContents(document, "concat(//child/@type, ':', //child/@value)"); assertThat(value, is("name:bob")); } @Test public void supportsReturningANumber() throws Exception{ Document document = Xml.document("<root><child type=\"name\" value=\"bob\"/></root>"); Number value = Xml.selectNumber(document, "count(//child)"); assertThat(value, NumberMatcher.is(1)); } @Test public void supportsReturningABoolean() throws Exception{ Document document = Xml.document("<root><child type=\"name\" value=\"bob\"/></root>"); boolean value = Xml.matches(document, "count(//child) = 1"); assertThat(value, is(true)); } @Test public void supportsUTF16() throws Exception { Document document = Xml.document("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\n"+ "<root><child><name>bob</name></child></root>"); Number value = Xml.selectNumber(document, "count(//child)"); assertThat(value, NumberMatcher.is(1)); } @Test public void nextOnNodeIteratorWorks() { Document document = Xml.document("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\n"+ "<root></root>"); Iterator<Node> value = Xml.selectNodes(document, "zerolength").iterator(); try { assertThat(value.next(), not(nullValue())); fail("Expected exception"); }catch (NoSuchElementException e){ // Expected } } }