Skip to content

Commit

Permalink
[ADD] XQuery, validate:...-report. Closes #1177
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianGruen committed Aug 24, 2015
1 parent 7b21a63 commit 1eb2f8f
Show file tree
Hide file tree
Showing 15 changed files with 513 additions and 263 deletions.
9 changes: 9 additions & 0 deletions basex-core/src/main/java/org/basex/query/func/Function.java
Expand Up @@ -1210,17 +1210,26 @@ ITEM_ZM, flag(HOF)),
_VALIDATE_XSD_INFO(ValidateXsdInfo.class, "xsd-info(input[,schema])",
arg(ITEM, ITEM), STR_ZM, flag(NDT), VALIDATE_URI),
/** XQuery function. */
_VALIDATE_XSD_REPORT(ValidateXsdReport.class, "xsd-report(input[,schema])",
arg(ITEM, ITEM), ELM, flag(NDT), VALIDATE_URI),
/** XQuery function. */
_VALIDATE_DTD(ValidateDtd.class, "dtd(input[,schema])", arg(ITEM, ITEM), EMP, flag(NDT),
VALIDATE_URI),
/** XQuery function. */
_VALIDATE_DTD_INFO(ValidateDtdInfo.class, "dtd-info(input[,schema])",
arg(ITEM, ITEM), STR_ZM, flag(NDT), VALIDATE_URI),
/** XQuery function. */
_VALIDATE_DTD_REPORT(ValidateDtdReport.class, "dtd-report(input[,schema])",
arg(ITEM, ITEM), ELM, flag(NDT), VALIDATE_URI),
/** XQuery function. */
_VALIDATE_RNG(ValidateRng.class, "rng(input,schema[,compact])",
arg(ITEM, ITEM, BLN), STR_ZM, flag(NDT), VALIDATE_URI),
/** XQuery function. */
_VALIDATE_RNG_INFO(ValidateRngInfo.class, "rng-info(input,schema[,compact])",
arg(ITEM, ITEM, BLN), STR_ZM, flag(NDT), VALIDATE_URI),
/** XQuery function. */
_VALIDATE_RNG_REPORT(ValidateRngReport.class, "rng-report(input,schema[,compact])",
arg(ITEM, ITEM, BLN), ELM, flag(NDT), VALIDATE_URI),

/* Web Module. */

Expand Down
@@ -1,9 +1,8 @@
package org.basex.query.func.validate;

import org.basex.core.*;
import java.util.*;

import org.basex.io.*;
import org.basex.util.*;
import org.basex.util.list.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

Expand All @@ -14,52 +13,56 @@
* @author Christian Gruen
*/
public final class ErrorHandler extends DefaultHandler {
/** Will contain all raised validation exception messages. */
private final TokenList exceptions = new TokenList();
/** Fatal error. */
static final String FATAL = "Fatal";
/** Error. */
static final String ERROR = "Error";
/** Warning. */
static final String WARNING = "Warning";

/** Errors. */
private final ArrayList<ErrorInfo> errors = new ArrayList<>();

/** Schema URL. */
private IO schema;

@Override
public void fatalError(final SAXParseException ex) {
error(ex, "Fatal");
add(ex, FATAL);
}

@Override
public void error(final SAXParseException ex) {
error(ex, "Error");
add(ex, ERROR);
}

@Override
public void warning(final SAXParseException ex) {
error(ex, "Warning");
add(ex, WARNING);
}

/**
* Adds an error message.
* Adds a new error info.
* @param ex exception
* @param type type of error
* @param level level
*/
void add(final SAXException ex, final String level) {
errors.add(new ErrorInfo(ex, level, schema));
}

/**
* Assigns the schema reference.
* @param io schema reference
*/
private void error(final SAXParseException ex, final String type) {
// may be recursively called if external validator (e.g. Saxon) is used
String msg = ex.getMessage();
if(msg.contains("Exception:")) {
Throwable e = ex;
while(e.getCause() != null) e = e.getCause();
if(e instanceof SAXException) msg = e.getLocalizedMessage();
} else {
final TokenBuilder report = new TokenBuilder();
final String id = ex.getSystemId();
if(id != null) report.add(IO.get(id).name()).add(", ");
report.addExt(ex.getLineNumber()).add(Text.COL).addExt(ex.getColumnNumber());
report.add(": ").add(msg);
msg = report.toString();
}
exceptions.add(type + Text.COL + msg);
void schema(final IO io) {
schema = io;
}

/**
* Returns the exception messages.
* @return exception messages
* Returns the errors.
* @return errors
*/
public TokenList getExceptions() {
return exceptions;
ArrayList<ErrorInfo> getErrors() {
return errors;
}
}
@@ -0,0 +1,61 @@
package org.basex.query.func.validate;

import org.basex.io.*;
import org.xml.sax.*;

/**
* Error info.
*
* @author BaseX Team 2005-15, BSD License
* @author Christian Gruen
*/
final class ErrorInfo {
/** Message. */
final String message;
/** Level. */
final String level;
/** URL. */
String url;
/** Line number. */
int line = Integer.MIN_VALUE;
/** Column number. */
int column = Integer.MIN_VALUE;

/**
* Constructor.
* @param ex exception
* @param level type
* @param schema schema url
*/
ErrorInfo(final SAXException ex, final String level, final IO schema) {
this.level = level;

String m = ex.getMessage();
Throwable e = ex;
if(m.contains("Exception:")) {
// may be recursively called if external validator (e.g. Saxon) is used
while(e.getCause() != null) e = e.getCause();
if(e instanceof SAXException) m = e.getLocalizedMessage();
}

if(ex instanceof SAXParseException) {
final SAXParseException se = (SAXParseException) ex;
final String id = se.getSystemId();
if(id != null) {
final IO io = IO.get(id);
if(schema == null || !io.isDir() && !schema.equals(id)) url = id;
}
line = se.getLineNumber();
column = se.getColumnNumber();
}
message = m;
}

@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
if(url != null) sb.append(url).append(", ");
if(line != Integer.MIN_VALUE) sb.append(line).append(':').append(column).append(": ");
return sb.append(message).toString();
}
}
@@ -1,17 +1,52 @@
package org.basex.query.func.validate;

import java.io.*;
import java.util.*;

import javax.xml.parsers.*;

import org.basex.io.*;
import org.basex.io.serial.*;
import org.basex.query.*;
import org.basex.query.value.*;
import org.basex.query.value.item.*;
import org.xml.sax.*;

/**
* Function implementation.
*
* @author BaseX Team 2005-15, BSD License
* @author Christian Gruen
*/
public final class ValidateDtd extends ValidateDtdInfo {
public class ValidateDtd extends ValidateFn {
@Override
public Value value(final QueryContext qc) throws QueryException {
return check(qc);
}

@Override
public ArrayList<ErrorInfo> errors(final QueryContext qc) throws QueryException {
checkCreate(qc);
return process(new Validation() {
@Override
void process(final ErrorHandler handler)
throws IOException, ParserConfigurationException, SAXException, QueryException {

final Item it = toNodeOrAtomItem(exprs[0], qc);
SerializerOptions sp = null;

// integrate doctype declaration via serialization parameters
if(exprs.length > 1) {
sp = new SerializerOptions();
final IO schema = prepare(checkPath(exprs[1], qc), handler);
sp.set(SerializerOptions.DOCTYPE_SYSTEM, schema.url());
}

final IO in = read(it, qc, sp);
final SAXParserFactory sf = SAXParserFactory.newInstance();
sf.setValidating(true);
sf.newSAXParser().parse(in.inputSource(), handler);
}
});
}
}
@@ -1,69 +1,17 @@
package org.basex.query.func.validate;

import java.io.*;

import javax.xml.parsers.*;

import org.basex.io.*;
import org.basex.io.serial.*;
import org.basex.query.*;
import org.basex.query.value.*;
import org.basex.query.value.item.*;
import org.xml.sax.*;

/**
* Validates a document against a DTD.
* The following two variants exist:
*
* <ul>{@code validate:dtd($doc)}
* <li>Looks for the document type declaration in {@code $doc} and
* uses it for validation.</li>
* <li>{@code $doc} must contain a DTD for this to work.</li>
* <li>{@code $doc} is allowed to be either a {@code XML node} or a {@code
* xs:string} pointing to an URL or a local file that will then be parsed
* and validated.</li>
* </ul>
* <ul>{@code validate:dtd($doc, $dtd)}
* <li>{@code $doc} is allowed to be either a {@code XML node} or a {@code
* xs:string} pointing to an URL or a local file</li>
* <li>{@code $dtd as xs:string} is expected to point to an URL or a local
* file containing the document type definitions. </li>
* </ul>
* Function implementation.
*
* @author BaseX Team 2005-15, BSD License
* @author Christian Gruen
*/
public class ValidateDtdInfo extends ValidateFn {
public final class ValidateDtdInfo extends ValidateDtd {
@Override
public Value value(final QueryContext qc) throws QueryException {
return info(qc);
}

@Override
public Value info(final QueryContext qc) throws QueryException {
checkCreate(qc);
return process(new Validation() {
@Override
void process(final ErrorHandler handler)
throws IOException, ParserConfigurationException, SAXException, QueryException {

final Item it = toNodeOrAtomItem(exprs[0], qc);
SerializerOptions sp = null;

// integrate doctype declaration via serialization parameters
if(exprs.length > 1) {
sp = new SerializerOptions();
IO dtd = checkPath(exprs[1], qc);
tmp = createTmp(dtd);
if(tmp != null) dtd = tmp;
sp.set(SerializerOptions.DOCTYPE_SYSTEM, dtd.url());
}

final IO in = read(it, qc, sp);
final SAXParserFactory sf = SAXParserFactory.newInstance();
sf.setValidating(true);
sf.newSAXParser().parse(in.inputSource(), handler);
}
});
}
}
@@ -0,0 +1,17 @@
package org.basex.query.func.validate;

import org.basex.query.*;
import org.basex.query.value.*;

/**
* Function implementation.
*
* @author BaseX Team 2005-15, BSD License
* @author Christian Gruen
*/
public final class ValidateDtdReport extends ValidateDtd {
@Override
public Value value(final QueryContext qc) throws QueryException {
return report(qc);
}
}

0 comments on commit 1eb2f8f

Please sign in to comment.