我可以在不写入临时文件的情况下验证 List<String> 中的 XML 吗?
Can I validate XML from List<String> without writing to temp file?
我需要根据 XSD 验证列表对象中的 XML。到目前为止,我只能验证 XML 个文件。截至目前,我正在将我的列表写入临时文件并验证该临时文件。我真的很想消除对该临时文件的需求。我的问题是 javax.xml.validation.Validator.validate 需要一个源,但我不知道如何将列表放入源中。
下面是我使用临时文件的工作源。
static String validate(List<String> xmlData, Schema schema) throws Exception {
File tmpFile = File.createTempFile("temp", ".xml"); // TODO: delete
StringBuilder exceptionList = new StringBuilder();
try {
Validator validator = schema.newValidator();
final List<SAXParseException> exceptions = new LinkedList<SAXParseException>();
validator.setErrorHandler(new ErrorHandler()
{
@Override
public void warning(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
@Override
public void fatalError(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
@Override
public void error(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
});
// TODO: remove this block
FileWriter fr = new FileWriter(tmpFile);
for (String str: xmlData) {
fr.write(str + System.lineSeparator());
}
fr.close();
//
validator.validate(new StreamSource(tmpFile)); // TODO: Here need xmlData instead
if (! exceptions.isEmpty() ) {
exceptions.forEach((temp) -> {
exceptionList.append(String.format("lineNumber: %s; columnNumber: %s; %s%s",
temp.getLineNumber(),temp.getColumnNumber(),temp.getMessage(),System.lineSeparator()));
});
}
return exceptionList.toString();
} catch (SAXException | IOException e) {
e.printStackTrace();
throw e;
} finally {
if (tmpFile.exists()) { tmpFile.delete(); } // TODO: delete
}
}
编辑:
为了后代,这里是新代码:
static String validate(String xmlData, Schema schema) throws Exception {
Reader sourceReader = null;
StringBuilder exceptionList = new StringBuilder();
try {
Validator validator = schema.newValidator();
final List<SAXParseException> exceptions = new LinkedList<SAXParseException>();
validator.setErrorHandler(new ErrorHandler()
{
@Override
public void warning(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
@Override
public void fatalError(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
@Override
public void error(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
});
sourceReader = new StringReader(xmlData);
validator.validate(new StreamSource(sourceReader));
if (! exceptions.isEmpty() ) {
exceptions.forEach((temp) -> {
exceptionList.append(String.format("lineNumber: %s; columnNumber: %s; %s%s",
temp.getLineNumber(),temp.getColumnNumber(),temp.getMessage(),System.lineSeparator()));
});
}
return exceptionList.toString();
} catch (SAXException | IOException e) {
e.printStackTrace();
throw e;
} finally {
if (sourceReader != null) { sourceReader.close(); }
}
}
您可以 assemble 一个字符串,然后将其包装在 Reader 中,如下所示:https://www.baeldung.com/java-convert-string-to-reader
然后您可以使用它来创建 StreamSource:https://docs.oracle.com/javase/7/docs/api/javax/xml/transform/stream/StreamSource.html#StreamSource(java.io.Reader)
javadoc 是你的朋友。
StreamSource
class 有一个带有 InputStream
参数的 constructor。
ByteArrayInputStream 扩展 InputStream
所以只需从 XML 字符串创建一个 ByteArrayInputStream
。
// import java.util.stream.Collectors;
String str = xmlData.stream()
.collect(Collectors.joining());
byte[] bytes = str.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
StreamSource source = new StreamSource(bais);
或者,您可以使用 XML 字符串中的 StreamSource
constructor that takes a Reader
parameter and create a StringReader。
String str = xmlData.stream()
.collect(Collectors.joining());
StringReader sr = new StringReader(str);
StreamSource source = new StreamSource(sr);
我需要根据 XSD 验证列表对象中的 XML。到目前为止,我只能验证 XML 个文件。截至目前,我正在将我的列表写入临时文件并验证该临时文件。我真的很想消除对该临时文件的需求。我的问题是 javax.xml.validation.Validator.validate 需要一个源,但我不知道如何将列表放入源中。
下面是我使用临时文件的工作源。
static String validate(List<String> xmlData, Schema schema) throws Exception {
File tmpFile = File.createTempFile("temp", ".xml"); // TODO: delete
StringBuilder exceptionList = new StringBuilder();
try {
Validator validator = schema.newValidator();
final List<SAXParseException> exceptions = new LinkedList<SAXParseException>();
validator.setErrorHandler(new ErrorHandler()
{
@Override
public void warning(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
@Override
public void fatalError(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
@Override
public void error(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
});
// TODO: remove this block
FileWriter fr = new FileWriter(tmpFile);
for (String str: xmlData) {
fr.write(str + System.lineSeparator());
}
fr.close();
//
validator.validate(new StreamSource(tmpFile)); // TODO: Here need xmlData instead
if (! exceptions.isEmpty() ) {
exceptions.forEach((temp) -> {
exceptionList.append(String.format("lineNumber: %s; columnNumber: %s; %s%s",
temp.getLineNumber(),temp.getColumnNumber(),temp.getMessage(),System.lineSeparator()));
});
}
return exceptionList.toString();
} catch (SAXException | IOException e) {
e.printStackTrace();
throw e;
} finally {
if (tmpFile.exists()) { tmpFile.delete(); } // TODO: delete
}
}
编辑: 为了后代,这里是新代码:
static String validate(String xmlData, Schema schema) throws Exception {
Reader sourceReader = null;
StringBuilder exceptionList = new StringBuilder();
try {
Validator validator = schema.newValidator();
final List<SAXParseException> exceptions = new LinkedList<SAXParseException>();
validator.setErrorHandler(new ErrorHandler()
{
@Override
public void warning(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
@Override
public void fatalError(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
@Override
public void error(SAXParseException exception) throws SAXException
{
exceptions.add(exception);
}
});
sourceReader = new StringReader(xmlData);
validator.validate(new StreamSource(sourceReader));
if (! exceptions.isEmpty() ) {
exceptions.forEach((temp) -> {
exceptionList.append(String.format("lineNumber: %s; columnNumber: %s; %s%s",
temp.getLineNumber(),temp.getColumnNumber(),temp.getMessage(),System.lineSeparator()));
});
}
return exceptionList.toString();
} catch (SAXException | IOException e) {
e.printStackTrace();
throw e;
} finally {
if (sourceReader != null) { sourceReader.close(); }
}
}
您可以 assemble 一个字符串,然后将其包装在 Reader 中,如下所示:https://www.baeldung.com/java-convert-string-to-reader
然后您可以使用它来创建 StreamSource:https://docs.oracle.com/javase/7/docs/api/javax/xml/transform/stream/StreamSource.html#StreamSource(java.io.Reader)
javadoc 是你的朋友。
StreamSource
class 有一个带有 InputStream
参数的 constructor。
ByteArrayInputStream 扩展 InputStream
所以只需从 XML 字符串创建一个 ByteArrayInputStream
。
// import java.util.stream.Collectors;
String str = xmlData.stream()
.collect(Collectors.joining());
byte[] bytes = str.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
StreamSource source = new StreamSource(bais);
或者,您可以使用 XML 字符串中的 StreamSource
constructor that takes a Reader
parameter and create a StringReader。
String str = xmlData.stream()
.collect(Collectors.joining());
StringReader sr = new StringReader(str);
StreamSource source = new StreamSource(sr);