W3CSchemaWriteNoNsTest.java
package stax2.vwstream;
import java.io.StringWriter;
import javax.xml.stream.XMLOutputFactory;
import org.codehaus.stax2.XMLStreamWriter2;
import org.codehaus.stax2.XMLOutputFactory2;
import org.codehaus.stax2.XMLStreamProperties;
import org.codehaus.stax2.validation.XMLValidationSchema;
import org.junit.jupiter.api.Test;
/**
* Regression test: writing an element via the 1-argument
* {@code writeStartElement(localName)} form must not inherit the parent's
* default namespace URI for validation. Schema child elements declared in
* no namespace ({@code elementFormDefault="unqualified"}) must pass
* validation even when a default namespace is in scope on the parent.
*
* @see <a href="https://github.com/FasterXML/woodstox/pull/245#issuecomment-4142056568">PR 245 comment</a>
*/
public class W3CSchemaWriteNoNsTest extends BaseOutputTest {
private static final String SCHEMA_UNQUALIFIED =
"<?xml version='1.0' encoding='UTF-8'?>\n" +
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'\n" +
" elementFormDefault='unqualified'>\n" +
" <xs:element name='Envelope'>\n" +
" <xs:complexType>\n" +
" <xs:sequence>\n" +
" <xs:element name='MessageHeader'>\n" +
" <xs:complexType>\n" +
" <xs:sequence>\n" +
" <xs:element name='MessageId' type='xs:string'/>\n" +
" </xs:sequence>\n" +
" </xs:complexType>\n" +
" </xs:element>\n" +
" <xs:element name='Body'>\n" +
" <xs:complexType>\n" +
" <xs:sequence>\n" +
" <xs:element name='Payload' type='xs:string'/>\n" +
" </xs:sequence>\n" +
" </xs:complexType>\n" +
" </xs:element>\n" +
" </xs:sequence>\n" +
" </xs:complexType>\n" +
" </xs:element>\n" +
"</xs:schema>";
/**
* 1-arg writeStartElement(localName) must not inherit the parent's
* default namespace for validation purposes.
*/
@Test
public void testWriteStartElementNoNsWithDefaultNsBound() throws Exception {
StringWriter strw = new StringWriter();
XMLValidationSchema schema = parseW3CSchema(SCHEMA_UNQUALIFIED);
XMLOutputFactory2 outf = getOutputFactory();
outf.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, Boolean.TRUE);
outf.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.FALSE);
XMLStreamWriter2 sw = (XMLStreamWriter2) outf.createXMLStreamWriter(strw);
sw.validateAgainst(schema);
sw.writeStartDocument();
sw.writeStartElement("Envelope");
sw.writeDefaultNamespace("urn:some:ns");
sw.writeStartElement("MessageHeader");
sw.writeStartElement("MessageId");
sw.writeCharacters("MSG-001");
sw.writeEndElement();
sw.writeEndElement();
sw.writeStartElement("Body");
sw.writeStartElement("Payload");
sw.writeCharacters("Hello");
sw.writeEndElement();
sw.writeEndElement();
sw.writeEndElement();
sw.writeEndDocument();
sw.close();
String xml = strw.toString();
assertTrue("Output should contain 'MessageHeader'", xml.contains("MessageHeader"));
assertTrue("Output should contain 'MSG-001'", xml.contains("MSG-001"));
}
private static final String SCHEMA_WITH_EMPTY_LEAF =
"<?xml version='1.0' encoding='UTF-8'?>\n" +
"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'\n" +
" elementFormDefault='unqualified'>\n" +
" <xs:element name='Root'>\n" +
" <xs:complexType>\n" +
" <xs:sequence>\n" +
" <xs:element name='Child' type='xs:string'/>\n" +
" <xs:element name='Empty'>\n" +
" <xs:complexType/>\n" +
" </xs:element>\n" +
" </xs:sequence>\n" +
" </xs:complexType>\n" +
" </xs:element>\n" +
"</xs:schema>";
/**
* 1-arg writeEmptyElement(localName) must also pass the correct empty
* URI to the validator when a default namespace is in scope on the parent.
*/
@Test
public void testWriteEmptyElementNoNsWithDefaultNsBound() throws Exception {
StringWriter strw = new StringWriter();
XMLValidationSchema schema = parseW3CSchema(SCHEMA_WITH_EMPTY_LEAF);
XMLOutputFactory2 outf = getOutputFactory();
outf.setProperty(XMLStreamProperties.XSP_NAMESPACE_AWARE, Boolean.TRUE);
outf.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.FALSE);
XMLStreamWriter2 sw = (XMLStreamWriter2) outf.createXMLStreamWriter(strw);
sw.validateAgainst(schema);
sw.writeStartDocument();
sw.writeStartElement("Root");
sw.writeDefaultNamespace("urn:some:ns");
sw.writeStartElement("Child");
sw.writeCharacters("value");
sw.writeEndElement();
sw.writeEmptyElement("Empty");
sw.writeEndElement();
sw.writeEndDocument();
sw.close();
String xml = strw.toString();
assertTrue("Output should contain 'Empty'", xml.contains("Empty"));
}
}