@Override public List<String> fromXml(XmlReader reader, TikXmlConfig config) throws IOException { List<String> list = new ArrayList<>(); while (reader.hasElement()) { // <a>a<a> // <b>b</b> // <c>c</c> reader.beginElement(); reader.nextElementName(); // Ignore element name String value = reader.nextTextContent(); list.add(value); reader.endElement(); } return list; }
@Override public Catalogue fromXml(XmlReader reader, TikXmlConfig config) throws IOException { Catalogue catalogue = new Catalogue(); catalogue.books = new ArrayList<>(); while (reader.hasElement()) { reader.beginElement(); if (reader.nextElementName().equals("book")) { catalogue.books.add((Book) config.getTypeAdapter(Book.class).fromXml(reader, config)); } reader.endElement(); } return catalogue; }
@Test public void notADocTypeDefinitionButSameDoctypeAsTag() throws IOException { String xml = "<!DOCTYPE foo><!DOCTYPE bar><DOCTYPE />"; XmlReader reader = readerFrom(xml); reader.beginElement(); Assert.assertEquals("DOCTYPE", reader.nextElementName()); Assert.assertFalse(reader.hasElement()); }
@Test public void emptyTextContent() throws IOException { String xml = "<element></element>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("element", reader.nextElementName()); Assert.assertFalse(reader.hasTextContent()); reader.endElement(); Assert.assertFalse(reader.hasElement()); Assert.assertEquals(XmlReader.XmlToken.END_OF_DOCUMENT, reader.peek()); } finally { reader.close(); } }
@Test public void noElementName() throws IOException { String xml = "<></>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); exception.expect(IOException.class); exception.expectMessage("Expected xml element name (literal expected) at path /"); reader.nextElementName(); } finally { reader.close(); } }
@Test public void jsonArrayTextContent() throws IOException { String xml = "<element><![CDATA[[{a:'b'}, {b:'c'}]]]></element>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("element", reader.nextElementName()); Assert.assertTrue(reader.hasTextContent()); Assert.assertEquals("[{a:'b'}, {b:'c'}]", reader.nextTextContent()); reader.endElement(); Assert.assertFalse(reader.hasElement()); Assert.assertEquals(XmlReader.XmlToken.END_OF_DOCUMENT, reader.peek()); } finally { reader.close(); } }
@Test public void noAttributesNoTextContent() throws IOException { String xml = "<foo></foo>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("foo", reader.nextElementName()); Assert.assertFalse(reader.hasAttribute()); Assert.assertFalse(reader.hasTextContent()); reader.endElement(); Assert.assertFalse(reader.hasElement()); Assert.assertEquals(XmlReader.XmlToken.END_OF_DOCUMENT, reader.peek()); } finally { reader.close(); } }
@Test public void skipTextContent() throws IOException { String xml = "<foo>Value</foo>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("foo", reader.nextElementName()); Assert.assertFalse(reader.hasAttribute()); Assert.assertTrue(reader.hasTextContent()); reader.skipTextContent(); reader.endElement(); Assert.assertFalse(reader.hasElement()); Assert.assertEquals(XmlReader.XmlToken.END_OF_DOCUMENT, reader.peek()); } finally { reader.close(); } }
@Test public void noAttributesButTextContent() throws IOException { String xml = "<foo>Value</foo>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("foo", reader.nextElementName()); Assert.assertFalse(reader.hasAttribute()); Assert.assertTrue(reader.hasTextContent()); Assert.assertEquals("Value", reader.nextTextContent()); reader.endElement(); Assert.assertFalse(reader.hasElement()); Assert.assertEquals(XmlReader.XmlToken.END_OF_DOCUMENT, reader.peek()); } finally { reader.close(); } }
@Test public void elementNamedDOCTYPEisRegularElement() throws IOException { String xml = "<root><DOCTYPE /></root>"; XmlReader reader = readerFrom(xml); reader.beginElement(); Assert.assertEquals("root", reader.nextElementName()); reader.beginElement(); Assert.assertEquals("DOCTYPE", reader.nextElementName()); reader.endElement(); reader.endElement(); Assert.assertFalse(reader.hasElement()); }
@Test public void incompleteDoubleQuoteAttribute() throws IOException { String xml = "<element a=\"foo ></element>"; XmlReader reader = readerFrom(xml); try { reader.hasElement(); reader.beginElement(); Assert.assertEquals("element", reader.nextElementName()); Assert.assertTrue(reader.hasAttribute()); Assert.assertEquals("a", reader.nextAttributeName()); exception.expect(IOException.class); exception.expectMessage( "Unterminated string (double quote \" is missing) at path /element[@a]"); reader.nextAttributeValue(); } finally { reader.close(); } }
@Test public void incompleteSingleQuoteAttribute() throws IOException { String xml = "<element a='foo />"; XmlReader reader = readerFrom(xml); try { reader.hasElement(); reader.beginElement(); Assert.assertEquals("element", reader.nextElementName()); Assert.assertTrue(reader.hasAttribute()); Assert.assertEquals("a", reader.nextAttributeName()); exception.expect(IOException.class); exception.expectMessage( "Unterminated string (single quote ' is missing) at path /element[@a]"); reader.nextAttributeValue(); } finally { reader.close(); } }
@Test public void readObjectWithMultilineComment() throws IOException { String xml = "<element><!-- comment \n multiline \n -->Value</element>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("element", reader.nextElementName()); Assert.assertTrue(reader.hasTextContent()); Assert.assertEquals(reader.nextTextContent(), "Value"); reader.endElement(); Assert.assertEquals(XmlReader.XmlToken.END_OF_DOCUMENT, reader.peek()); } finally { reader.close(); } }
@Test public void xmlWithLowercaseDoctypes() throws IOException { String xml = "<!doctype rootelement SYSTEM \"file.dtd\"><root\nanAttribute=\"1\"\n attributeWithWhiteSpace=\"2\" \n \t\tattributeWithTabs=\"20.2\">\n<child>Contains\nmulitlines\n</child>\n</root>"; XmlReader reader = readerFrom(xml); reader.beginElement(); Assert.assertEquals("root", reader.nextElementName()); Assert.assertEquals("anAttribute", reader.nextAttributeName()); Assert.assertEquals(1, reader.nextAttributeValueAsInt()); Assert.assertEquals("attributeWithWhiteSpace", reader.nextAttributeName()); Assert.assertEquals("2", reader.nextAttributeValue()); Assert.assertEquals("attributeWithTabs", reader.nextAttributeName()); Assert.assertEquals(20.2, reader.nextAttributeValueAsDouble(), 0); Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("child", reader.nextElementName()); Assert.assertEquals("Contains\nmulitlines\n", reader.nextTextContent()); reader.endElement(); reader.endElement(); Assert.assertFalse(reader.hasElement()); }
@Test public void skipUncompleteTextContent() throws IOException { String xml = "<foo>Value"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("foo", reader.nextElementName()); Assert.assertFalse(reader.hasAttribute()); Assert.assertTrue(reader.hasTextContent()); exception.expect(IOException.class); exception.expectMessage( "Unterminated element text content. Expected </foo> but haven't found at path /foo/text()"); reader.skipTextContent(); } finally { reader.close(); } }
@Test public void callingSkipRemainingElementInWrongPlace() throws IOException { String xml = "<foo><e1></e1><bar a='1' b='2'>TextContent<child a='1'>Child text Value<other b='123'>Text<inline /></other></child> <![CDATA[some <cdata></> &]]> </bar>TextAfterSkippedElement<element></element></foo>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("foo", reader.nextElementName()); reader.beginElement(); Assert.assertEquals("e1", reader.nextElementName()); reader.endElement(); exception.expect(AssertionError.class); exception.expectMessage( "This method can only be invoked after having consumed the opening element via beginElement()"); reader.skipRemainingElement(); // Forgot to call beginElement() before } finally { reader.close(); } }
@Test public void skipRemainingElementUnclosed() throws IOException { String xml = "<foo><e1></e1><bar a='1' b='2'>TextContent<child a='1'>Child text Value<other b='123'>Text<inline /></other> <![CDATA[some <cdata></> &]]>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("foo", reader.nextElementName()); reader.beginElement(); Assert.assertEquals("e1", reader.nextElementName()); reader.endElement(); reader.beginElement(); // <bar> element exception.expect(IOException.class); exception.expectMessage("Unexpected end of input at path /foo/bar/child/text()"); reader.skipRemainingElement(); // skip <bar> } finally { reader.close(); } }
@Test public void missingClosingTag() throws IOException { String xml = "<element a='foo' >"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("element", reader.nextElementName()); Assert.assertTrue(reader.hasAttribute()); Assert.assertEquals("a", reader.nextAttributeName()); Assert.assertEquals("foo", reader.nextAttributeValue()); exception.expect(IOException.class); exception.expectMessage("Unexpected end of input at path /element/text()"); reader.endElement(); } finally { reader.close(); } }
@Test public void missingClosingCDATA() throws IOException { String cdata = "< hello <> & cdata</foo>"; String xml = "<foo>NormalValue<![CDATA[" + cdata + "nextvalue</foo>"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("foo", reader.nextElementName()); Assert.assertFalse(reader.hasAttribute()); Assert.assertTrue(reader.hasTextContent()); Assert.assertEquals("NormalValue", reader.nextTextContent()); exception.expect(IOException.class); exception.expectMessage("<![CDATA[ at /foo/text() has never been closed with ]]>"); Assert.assertEquals(cdata, reader.nextTextContent()); } finally { reader.close(); } }
@Test public void inlineClosing() throws IOException { String xml = "<element a='foo' />"; XmlReader reader = readerFrom(xml); try { Assert.assertTrue(reader.hasElement()); reader.beginElement(); Assert.assertEquals("element", reader.nextElementName()); Assert.assertTrue(reader.hasAttribute()); Assert.assertEquals("a", reader.nextAttributeName()); Assert.assertEquals("foo", reader.nextAttributeValue()); Assert.assertEquals(XmlReader.XmlToken.ELEMENT_END, reader.peek()); reader.endElement(); Assert.assertEquals(XmlReader.XmlToken.END_OF_DOCUMENT, reader.peek()); } finally { reader.close(); } }