【问题标题】:Can I validate XML from List<String> without writing to temp file?我可以在不写入临时文件的情况下从 List<String> 验证 XML 吗?
【发布时间】:2020-10-28 14:05:49
【问题描述】:

我在需要针对 XSD 进行验证的 List 对象中有 XML。到目前为止,我只能验证 XML 文件。截至目前,我正在将我的列表写入一个临时文件并验证该临时文件。我真的很想消除对那个临时文件的需要。我的问题是 javax.xml.validation.Validator.validate 需要一个 Source,但我不知道如何将 List 放入 Source。

以下是我使用临时文件的工作源。

     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(); }
        }
    }

【问题讨论】:

    标签: java xml validation javax.xml


    【解决方案1】:

    您可以组装一个字符串,然后将其包装在 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)

    【讨论】:

      【解决方案2】:

      javadoc 是你的朋友。
      StreamSource 类有一个 constructor,它接受一个 InputStream 参数。
      ByteArrayInputStream 扩展 InputStream 所以只需创建一个 @ 987654328@ 来自 XML 字符串。

      // 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);
      

      或者,您可以使用带有Reader 参数的StreamSource constructor,并从XML 字符串创建StringReader

      String str = xmlData.stream()
                          .collect(Collectors.joining());
      StringReader sr = new StringReader(str);
      StreamSource source = new StreamSource(sr);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-19
        • 2023-03-16
        • 2015-05-24
        • 1970-01-01
        • 2014-11-09
        • 1970-01-01
        • 2014-12-03
        • 1970-01-01
        相关资源
        最近更新 更多