Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WstxValidationException: Unknown reason (at end element </nl:nillableIntElement>) when validating a document with nillable elements #187

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 151 additions & 55 deletions src/main/java/com/ctc/wstx/sw/BaseNsStreamWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
import javax.xml.stream.events.StartElement;

import org.codehaus.stax2.ri.typed.AsciiValueEncoder;
import org.codehaus.stax2.validation.XMLValidationException;
import org.codehaus.stax2.validation.XMLValidationSchema;
import org.codehaus.stax2.validation.XMLValidator;

import com.ctc.wstx.api.EmptyElementHandler;
import com.ctc.wstx.api.WriterConfig;
import com.ctc.wstx.api.WstxInputProperties;
import com.ctc.wstx.cfg.ErrorConsts;
import com.ctc.wstx.cfg.XmlConsts;
import com.ctc.wstx.exc.WstxIOException;
import com.ctc.wstx.util.DefaultXmlSymbolTable;

Expand Down Expand Up @@ -246,9 +249,6 @@ public void writeEmptyElement(String localName)
throws XMLStreamException
{
checkStartElement(localName, null);
if (mValidator != null) {
mValidator.validateElementStart(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX);
}
mEmptyElement = true;
if (mOutputElemPool != null) {
SimpleOutputElement newCurr = mOutputElemPool;
Expand Down Expand Up @@ -294,9 +294,6 @@ public void writeStartElement(String localName)
throws XMLStreamException
{
checkStartElement(localName, null);
if (mValidator != null) {
mValidator.validateElementStart(localName, XmlConsts.ELEM_NO_NS_URI, XmlConsts.ELEM_NO_PREFIX);
}
mEmptyElement = false;
if (mOutputElemPool != null) {
SimpleOutputElement newCurr = mOutputElemPool;
Expand Down Expand Up @@ -334,19 +331,19 @@ protected void writeTypedAttribute(String prefix, String nsURI, String localName
if (!mStartElementOpen) {
throwOutputError(ErrorConsts.WERR_ATTR_NO_ELEM);
}
if (mCheckAttrs) { // still need to ensure no duplicate attrs?
mCurrElem.checkAttrWrite(nsURI, localName);
}
try {
if (mValidator == null) {
if (mCheckAttrs) { // still need to ensure no duplicate attrs?
mCurrElem.addAttribute(nsURI, localName, null, null);
}
if (prefix == null || prefix.length() == 0) {
mWriter.writeTypedAttribute(localName, enc);
} else {
mWriter.writeTypedAttribute(prefix, localName, enc);
}
} else {
mWriter.writeTypedAttribute
(prefix, localName, nsURI, enc, mValidator, getCopyBuffer());
(prefix, localName, nsURI, enc, mCurrElem.getAttributeCollector(), getCopyBuffer());
}
} catch (IOException ioe) {
throw new WstxIOException(ioe);
Expand Down Expand Up @@ -430,7 +427,16 @@ protected void closeStartElement(boolean emptyElem)
}

if (mValidator != null) {
mVldContent = mValidator.validateElementAndAttributes();
try {
mVldContent = mCurrElem.validateElementStartAndAttributes();
if (emptyElem) {
mVldContent = mValidator.validateElementEnd
(mCurrElem.getLocalName(), mCurrElem.getNamespaceURI(), mCurrElem.getPrefix());
}
} catch (XMLValidationException e) {
mVldException = e;
throw e;
}
}

// Need bit more special handling for empty elements...
Expand All @@ -440,10 +446,6 @@ protected void closeStartElement(boolean emptyElem)
if (mCurrElem.isRoot()) { // Did we close the root? (isRoot() returns true for the virtual "document node")
mState = STATE_EPILOG;
}
if (mValidator != null) {
mVldContent = mValidator.validateElementEnd
(curr.getLocalName(), curr.getNamespaceURI(), curr.getPrefix());
}
if (mPoolSize < MAX_POOL_SIZE) {
curr.addToPool(mOutputElemPool);
mOutputElemPool = curr;
Expand Down Expand Up @@ -471,6 +473,9 @@ protected String getTopElementDesc() {
protected void checkStartElement(String localName, String prefix)
throws XMLStreamException
{
if (mVldException != null) {
throw new XMLStreamException("Cannot start an element after a validation error", mVldException);
}
// Need to finish an open start element?
if (mStartElementOpen) {
closeStartElement(mEmptyElement);
Expand All @@ -493,13 +498,14 @@ protected final void doWriteAttr(String localName, String nsURI, String prefix,
String value)
throws XMLStreamException
{
if (mCheckAttrs) { // still need to ensure no duplicate attrs?
mCurrElem.checkAttrWrite(nsURI, localName);
}
if (mValidator != null) {
// No need to get it normalized... even if validator does normalize
// it, we don't use that for anything
mValidator.validateAttribute(localName, nsURI, prefix, value);
if (mCheckAttrs) {
// ensure no duplicate attrs and possibly pass them to validator when closing the start element
try {
mCurrElem.addAttribute(nsURI, localName, prefix, value);
} catch (XMLValidationException e) {
mVldException = e;
throw e;
}
}
try {
int vlen = value.length();
Expand Down Expand Up @@ -532,29 +538,6 @@ protected final void doWriteAttr(String localName, String nsURI, String prefix,
}
}

protected final void doWriteAttr(String localName, String nsURI, String prefix,
char[] buf, int start, int len)
throws XMLStreamException
{
if (mCheckAttrs) { // still need to ensure no duplicate attrs?
mCurrElem.checkAttrWrite(nsURI, localName);
}
if (mValidator != null) {
// No need to get it normalized... even if validator does normalize
// it, we don't use that for anything
mValidator.validateAttribute(localName, nsURI, prefix, buf, start, len);
}
try {
if (prefix != null && prefix.length() > 0) {
mWriter.writeAttribute(prefix, localName, buf, start, len);
} else {
mWriter.writeAttribute(localName, buf, start, len);
}
} catch (IOException ioe) {
throw new WstxIOException(ioe);
}
}

protected void doWriteNamespace(String prefix, String nsURI)
throws XMLStreamException
{
Expand Down Expand Up @@ -653,11 +636,28 @@ protected void doWriteEndTag(QName expName, boolean allowEmpty)
}

// Better have something to close... (to figure out what to close)
if (mState != STATE_TREE) {
if (mVldException != null) {
throw new XMLStreamException("Cannot start an element after a validation error", mVldException);
} else if (mState != STATE_TREE) {
// Have to always throw exception... don't necessarily know the name
reportNwfStructure("No open start element, when trying to write end element");
}

if (mStartElementOpen) {
if (mValidator != null) {
// We need to validate here, before we move the mCurrElem
try {
/* Note: return value is not of much use, since the
* element will be closed right away...
*/
mVldContent = mCurrElem.validateElementStartAndAttributes();
} catch (XMLValidationException e) {
mVldException = e;
throw e;
}
}
}

SimpleOutputElement thisElem = mCurrElem;
String prefix = thisElem.getPrefix();
String localName = thisElem.getLocalName();
Expand Down Expand Up @@ -691,12 +691,6 @@ protected void doWriteEndTag(QName expName, boolean allowEmpty)
/* Can't/shouldn't call closeStartElement, but need to do same
* processing. Thus, this is almost identical to closeStartElement:
*/
if (mValidator != null) {
/* Note: return value is not of much use, since the
* element will be closed right away...
*/
mVldContent = mValidator.validateElementAndAttributes();
}
mStartElementOpen = false;
try {
//If an EmptyElementHandler is provided use it to determine if allowEmpty is set
Expand All @@ -710,7 +704,12 @@ protected void doWriteEndTag(QName expName, boolean allowEmpty)
mState = STATE_EPILOG;
}
if (mValidator != null) {
mVldContent = mValidator.validateElementEnd(localName, nsURI, prefix);
try {
mVldContent = mValidator.validateElementEnd(localName, nsURI, prefix);
} catch (XMLValidationException e) {
mVldException = e;
throw e;
}
}
return;
}
Expand All @@ -733,7 +732,12 @@ protected void doWriteEndTag(QName expName, boolean allowEmpty)

// Ok, time to validate...
if (mValidator != null) {
mVldContent = mValidator.validateElementEnd(localName, nsURI, prefix);
try {
mVldContent = mValidator.validateElementEnd(localName, nsURI, prefix);
} catch (XMLValidationException e) {
mVldException = e;
throw e;
}
}
}

Expand Down Expand Up @@ -763,4 +767,96 @@ protected abstract void writeStartOrEmpty(String localName, String nsURI)

protected abstract void writeStartOrEmpty(String prefix, String localName, String nsURI)
throws XMLStreamException;

/*
///////////////////////////////////////////////////////////////////////
// Attribute access
///////////////////////////////////////////////////////////////////////
*/

@Override
public int getAttributeCount()
{
return mCurrElem.getAttributeCount();
}

@Override
public String getAttributeLocalName(int index)
{
return mCurrElem.getAttributeLocalName(index);
}

@Override
public String getAttributeNamespace(int index)
{
return mCurrElem.getAttributeNamespace(index);
}

@Override
public String getAttributePrefix(int index)
{
return mCurrElem.getAttributePrefix(index);
}

@Override
public String getAttributeValue(int index)
{
return mCurrElem.getAttributeValue(index);
}

@Override
public String getAttributeValue(String nsURI, String localName)
{
return mCurrElem.getAttributeValue(nsURI, localName);
}

@Override
public String getAttributeType(int index) {
return (mValidator == null) ? WstxInputProperties.UNKNOWN_ATTR_TYPE :
mValidator.getAttributeType(index);
}

@Override
public int findAttributeIndex(String nsURI, String localName)
{
return mCurrElem.findAttributeIndex(nsURI, localName);
}

/*
///////////////////////////////////////////////////////////////////////
// Overrides to keep the validator up to date in SimpleOutputElement instances
///////////////////////////////////////////////////////////////////////
*/

@Override
public XMLValidator validateAgainst(XMLValidationSchema schema) throws XMLStreamException {
final XMLValidator validateAgainst = super.validateAgainst(schema);
mCurrElem.setValidator(mValidator);
if (mOutputElemPool != null) {
mOutputElemPool.setValidator(mValidator);
}
return validateAgainst;
}

@Override
public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) throws XMLStreamException {
final XMLValidator result = super.stopValidatingAgainst(schema);
mCurrElem.setValidator(mValidator);
if (mOutputElemPool != null) {
mOutputElemPool.setValidator(mValidator);
}
return result;
}

@Override
public XMLValidator stopValidatingAgainst(XMLValidator validator) throws XMLStreamException {
final XMLValidator result = super.stopValidatingAgainst(validator);
mCurrElem.setValidator(mValidator);
if (mOutputElemPool != null) {
mOutputElemPool.setValidator(mValidator);
}
return result;
}


}
Loading