package org.codehaus.stax.test.evt;
import java.util.*;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.*;
import javax.xml.stream.events.*;
/**
* Unit tests for testing that START_ELEMENT event object behaves
* as expected
*
* @author Tatu Saloranta
*/
public class TestStartElem
extends BaseEventTest
{
/**
* Simple tests to ensure that the namespace declarations are properly
* parsed and accessible via {@link StartElement}.
*/
public void testStartElemNs()
throws XMLStreamException
{
String XML = "<root xmlns='http://my' xmlns:a='ns:attrs' "
+"attr1='value1' a:attr2='value2'"
+"/>";
XMLEventReader er = getReader(XML, true, false);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
XMLEvent evt = er.nextEvent();
assertTokenType(START_ELEMENT, evt.getEventType());
// Ok, got the start element... is it ok?
assertTrue(evt.isStartElement());
StartElement se = evt.asStartElement();
testEventWritability(se);
NamespaceContext nsCtxt = se.getNamespaceContext();
assertNotNull("StartElement.getNamespaceContext() should never return null", nsCtxt);
// First, ones we shouldn't get:
assertNull(nsCtxt.getPrefix("a"));
assertNull(nsCtxt.getPrefix("http://foobar"));
assertNull(nsCtxt.getNamespaceURI("b"));
assertNull(nsCtxt.getNamespaceURI("http://my"));
{
Iterator it = nsCtxt.getPrefixes("http://foobar");
// Specs don't specify if we should get null, or empty iterator
assertTrue((it == null) || !it.hasNext());
it = nsCtxt.getPrefixes("a");
assertTrue((it == null) || !it.hasNext());
}
// Then ones we should:
assertEquals("a", nsCtxt.getPrefix("ns:attrs"));
assertEquals("", nsCtxt.getPrefix("http://my"));
assertEquals("http://my", nsCtxt.getNamespaceURI(""));
assertEquals("ns:attrs", nsCtxt.getNamespaceURI("a"));
// Plus, let's check the other namespace access:
Iterator it = se.getNamespaces();
assertEquals(2, countElements(it));
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
assertTokenType(END_DOCUMENT, er.nextEvent().getEventType());
assertFalse(er.hasNext());
}
public void testNestedStartElemNs()
throws XMLStreamException
{
String XML = "<root><leaf xmlns='x' />"
+"<branch xmlns:a='b' xmlns:x='url'>"
+"<leaf xmlns:a='c' x:attr='value'/></branch>"
+"</root>";
XMLEventReader er = getReader(XML, true, false);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
XMLEvent evt = er.nextEvent();
assertTokenType(START_ELEMENT, evt.getEventType());
StartElement se = evt.asStartElement();
testEventWritability(se);
// Let's first check that it has 1 declaration:
assertEquals(0, countElements(se.getNamespaces()));
NamespaceContext nsCtxt = se.getNamespaceContext();
assertNotNull("StartElement.getNamespaceContext() should never return null", nsCtxt);
assertNull(nsCtxt.getPrefix("a"));
assertNull(nsCtxt.getNamespaceURI("b"));
// then first leaf:
evt = er.nextEvent();
assertTrue(evt.isStartElement());
se = evt.asStartElement();
assertEquals("leaf", se.getName().getLocalPart());
assertEquals(1, countElements(se.getNamespaces()));
assertEquals("x", se.getName().getNamespaceURI());
nsCtxt = se.getNamespaceContext();
assertEquals("x", nsCtxt.getNamespaceURI(""));
assertEquals("", nsCtxt.getPrefix("x"));
testEventWritability(se);
evt = er.nextEvent();
assertTrue(evt.isEndElement());
testEventWritability(evt);
// Ok, branch:
evt = er.nextEvent();
assertTrue(evt.isStartElement());
se = evt.asStartElement();
assertEquals("branch", se.getName().getLocalPart());
assertEquals(2, countElements(se.getNamespaces()));
nsCtxt = se.getNamespaceContext();
assertEquals("a", nsCtxt.getPrefix("b"));
assertEquals("b", nsCtxt.getNamespaceURI("a"));
assertEquals("x", nsCtxt.getPrefix("url"));
assertEquals("url", nsCtxt.getNamespaceURI("x"));
testEventWritability(se);
// second leaf
evt = er.nextEvent();
assertTrue(evt.isStartElement());
se = evt.asStartElement();
nsCtxt = se.getNamespaceContext();
assertEquals("leaf", se.getName().getLocalPart());
// only one declared in this particular element
assertEquals(1, countElements(se.getNamespaces()));
// but should still show the other bound ns from parent
nsCtxt = se.getNamespaceContext();
assertEquals("a", nsCtxt.getPrefix("c"));
assertEquals("c", nsCtxt.getNamespaceURI("a"));
assertEquals("x", nsCtxt.getPrefix("url"));
assertEquals("url", nsCtxt.getNamespaceURI("x"));
// ok, but how about masking:
assertNull(nsCtxt.getPrefix("b"));
// Ok, fine... others we don't care about:
assertTrue(er.nextEvent().isEndElement());
}
/**
* Another unit test, one that checks a special case of namespace
* enclosures and namespace context objects.
*/
public void testNestedStartElemNs2()
throws XMLStreamException
{
String XML = "<root><branch xmlns:a='url'><leaf /></branch></root>";
XMLEventReader er = getReader(XML, true, false);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
XMLEvent evt = er.nextEvent(); // root
assertTokenType(START_ELEMENT, evt.getEventType());
StartElement se = evt.asStartElement();
assertEquals("root", se.getName().getLocalPart());
assertEquals(0, countElements(se.getNamespaces()));
evt = er.nextEvent(); // branch
assertTokenType(START_ELEMENT, evt.getEventType());
se = evt.asStartElement();
assertEquals("branch", se.getName().getLocalPart());
assertEquals(1, countElements(se.getNamespaces()));
NamespaceContext nsCtxt = se.getNamespaceContext();
assertNotNull("StartElement.getNamespaceContext() should never return null", nsCtxt);
assertEquals("url", nsCtxt.getNamespaceURI("a"));
assertEquals("a", nsCtxt.getPrefix("url"));
evt = er.nextEvent(); // leaf
assertTokenType(START_ELEMENT, evt.getEventType());
se = evt.asStartElement();
assertEquals("leaf", se.getName().getLocalPart());
assertEquals(0, countElements(se.getNamespaces()));
nsCtxt = se.getNamespaceContext();
assertEquals("url", nsCtxt.getNamespaceURI("a"));
assertEquals("a", nsCtxt.getPrefix("url"));
assertTrue(er.nextEvent().isEndElement()); // /leaf
assertTrue(er.nextEvent().isEndElement()); // /branch
assertTrue(er.nextEvent().isEndElement()); // /root
}
/**
* Test to check that attributes can be accessed normally via
* {@link StartElement} instances.
*/
public void testStartElemAttrs()
throws XMLStreamException
{
String XML = "<root xmlns:a='ns:attrs' "
+"attr1='value1' a:attr2='value2'"
+"><leaf xmlns='url:ns2' attr='x' /></root>";
XMLEventReader er = getReader(XML, true, false);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
XMLEvent evt = er.nextEvent();
assertTokenType(START_ELEMENT, evt.getEventType());
StartElement se = evt.asStartElement();
assertAttr(se, "", "attr1", "value1");
// ... and same without ns uri being passed
assertNqAttr(se, "attr1", "value1");
assertAttr(se, "ns:attrs", "attr2", "value2");
assertAttr(se, "", "attr2", null);
assertNqAttr(se, "attr2", null);
assertAttr(se, "ns:attrs", "attr1", null);
evt = er.nextEvent();
assertTokenType(START_ELEMENT, evt.getEventType());
se = evt.asStartElement();
// One we should find (note: def. ns is not used!)
assertAttr(se, "", "attr", "x");
assertNqAttr(se, "attr", "x");
// and then ones that aren't there...
assertAttr(se, "url:ns2", "attr", null);
assertAttr(se, "url:ns2", "x", null);
assertAttr(se, "ns:foo", "foobar", null);
assertAttr(se, "", "attr1", null);
assertNqAttr(se, "attr1", null);
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
assertTokenType(END_DOCUMENT, er.nextEvent().getEventType());
}
public void testStartElemManyAttrsNs()
throws XMLStreamException
{
XMLEventReader er = getReader(get11AttrDoc(), true, false);
assertTokenType(START_DOCUMENT, er.nextEvent().getEventType());
XMLEvent evt = er.nextEvent();
assertTokenType(START_ELEMENT, evt.getEventType());
StartElement se = evt.asStartElement();
assertEquals(11, countElements(se.getAttributes()));
// Let's verify we can find all attrs:
for (int i = ATTR11_NAMES.length; --i >= 0; ) {
String name = ATTR11_NAMES[i];
String value = ATTR11_VALUES[i];
// First, via string constant:
assertAttr11Value(se, name, value);
// Then using non-interned:
assertAttr11Value(se, ""+name, value);
// Then that non-existing ones are not found:
String start = name.substring(0, 1);
assertAttr11Value(se, name+start, null);
assertAttr11Value(se, start+name, null);
}
assertTokenType(END_ELEMENT, er.nextEvent().getEventType());
er.close();
}
/*
/////////////////////////////////////////////////
// Internal methods:
/////////////////////////////////////////////////
*/
final static String[] ATTR11_NAMES = new String[] {
"method", "activeShell", "source", "data",
"widget", "length", "start", "styledTextNewValue",
"replacedText", "styledTextFunction", "raw"
};
final static String[] ATTR11_VALUES = new String[] {
"a", "x", "y", "z",
"a", "1", "2", "t",
"", "f", "b"
};
private void assertAttr11Value(StartElement elem, String localName, String expValue)
{
String msg = "Wrong value for attribute '"+localName+"'; ";
Attribute attr = elem.getAttributeByName(new QName(localName));
String actValue = (attr == null) ? null : attr.getValue();
if (expValue == null) {
assertNull(msg, actValue);
} else {
assertEquals(msg, expValue, actValue);
}
// Let's also try with the other qname constructors, just to be sure
attr = elem.getAttributeByName(new QName("", localName));
actValue = (attr == null) ? null : attr.getValue();
if (expValue == null) {
assertNull(msg, actValue);
} else {
assertEquals(msg, expValue, actValue);
}
attr = elem.getAttributeByName(new QName("", localName, ""));
actValue = (attr == null) ? null : attr.getValue();
if (expValue == null) {
assertNull(msg, actValue);
} else {
assertEquals(msg, expValue, actValue);
}
}
private String get11AttrDoc()
{
StringBuffer sb = new StringBuffer();
sb.append("<root");
for (int i = 0; i < ATTR11_NAMES.length; ++i) {
sb.append(' ');
sb.append(ATTR11_NAMES[i]);
sb.append('=');
sb.append(((i & 1) == 0) ? '"' : '\'');
// Assuming no quoting needed
sb.append(ATTR11_VALUES[i]);
sb.append(((i & 1) == 0) ? '"' : '\'');
}
sb.append(" />");
return sb.toString();
}
private int countElements(Iterator it) {
int count = 0;
if (it != null) {
while (it.hasNext()) {
++count;
it.next();
}
}
return count;
}
private void assertAttr(StartElement se, String nsURI, String localName,
String expValue)
{
QName qn = new QName(nsURI, localName);
Attribute attr = se.getAttributeByName(qn);
if (expValue == null) {
assertNull("Should not find attribute '"+qn+"'", attr);
} else {
assertNotNull("Should find attribute '"+qn+"' but got null", attr);
assertEquals("Attribute '"+qn+"' has unexpected value",
expValue, attr.getValue());
}
}
private void assertNqAttr(StartElement se, String localName, String expValue)
{
QName qn = new QName(localName);
Attribute attr = se.getAttributeByName(qn);
if (expValue == null) {
assertNull("Should not find attribute '"+qn+"'", attr);
} else {
assertNotNull("Should find attribute '"+qn+"' but got null", attr);
assertEquals("Attribute '"+qn+"' has unexpected value",
expValue, attr.getValue());
}
/* 21-Sep-2006, TSa: Let's also try it with different QName
* constructor, just to be sure
*/
qn = new QName("", localName);
attr = se.getAttributeByName(qn);
if (expValue == null) {
assertNull("Should not find attribute '"+qn+"'", attr);
} else {
assertNotNull("Should find attribute '"+qn+"' but got null", attr);
assertEquals("Attribute '"+qn+"' has unexpected value",
expValue, attr.getValue());
}
}
private XMLEventReader getReader(String contents, boolean nsAware,
boolean coalesce)
throws XMLStreamException
{
XMLInputFactory f = getInputFactory();
setNamespaceAware(f, nsAware);
setCoalescing(f, coalesce);
setSupportDTD(f, true);
setValidating(f, false);
return constructEventReader(f, contents);
}
}