Код IT
← Каталог

Практикум Swing — XML-валидатор — Два публичных метода `validate`

Фрагмент из «Практикум Swing — XML-валидатор»: Два публичных метода `validate`.

Java main.java
package com.xmlvalidator.service;

import com.xmlvalidator.model.ValidationResult;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public final class XsdValidatorService {

    public ValidationResult validate(Path xmlPath, Path xsdPath) {
        if (xmlPath == null || !Files.isRegularFile(xmlPath)) {
            return ValidationResult.configurationError("Укажите существующий XML-файл.");
        }
        if (xsdPath == null || !Files.isRegularFile(xsdPath)) {
            return ValidationResult.configurationError("Укажите существующий XSD-файл.");
        }

        Source xmlSource = new StreamSource(xmlPath.toFile());
        xmlSource.setSystemId(xmlPath.toUri().toString());
        return validate(xmlSource, new StreamSource(xsdPath.toFile()));
    }

    public ValidationResult validate(String xmlContent, String xsdContent) {
        if (xmlContent == null || xmlContent.isBlank()) {
            return ValidationResult.configurationError("XML не может быть пустым.");
        }
        if (xsdContent == null || xsdContent.isBlank()) {
            return ValidationResult.configurationError("XSD не может быть пустым.");
        }

        Source xmlSource = streamSource(xmlContent, "inline.xml");
        Source xsdSource = streamSource(xsdContent, "inline.xsd");
        return validate(xmlSource, xsdSource);
    }

    private ValidationResult validate(Source xmlSource, Source xsdSource) {
        try {
            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
            factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file");

            Schema schema = factory.newSchema(xsdSource);
            Validator validator = schema.newValidator();
            validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
            validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file");

            ValidationResult.Builder builder = new ValidationResult.Builder();
            validator.setErrorHandler(new CollectingErrorHandler(builder));
            validator.validate(xmlSource);
            return builder.build();
        } catch (SAXException ex) {
            if (ex instanceof SAXParseException parseEx) {
                return ValidationResult.failure(List.of(new ValidationResult.ValidationError(
                        parseEx.getMessage(),
                        parseEx.getLineNumber() > 0 ? parseEx.getLineNumber() : null,
                        parseEx.getColumnNumber() > 0 ? parseEx.getColumnNumber() : null,
                        "fatal"
                )));
            }
            return ValidationResult.configurationError("Ошибка схемы или XML: " + ex.getMessage());
        } catch (IOException ex) {
            return ValidationResult.configurationError("Ошибка чтения: " + ex.getMessage());
        }
    }

    private static Source streamSource(String content, String systemId) {
        InputStream input = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
        StreamSource source = new StreamSource(input, systemId);
        source.setSystemId(systemId);
        return source;
    }

    private static final class CollectingErrorHandler implements ErrorHandler {
        private final ValidationResult.Builder builder;

        private CollectingErrorHandler(ValidationResult.Builder builder) {
            this.builder = builder;
        }

        @Override
        public void warning(SAXParseException exception) {
            add(exception, "warning");
        }

        @Override
        public void error(SAXParseException exception) {
            add(exception, "error");
        }

        @Override
        public void fatalError(SAXParseException exception) throws SAXException {
            add(exception, "fatal");
            throw exception;
        }

        private void add(SAXParseException exception, String severity) {
            builder.addError(
                    exception.getMessage(),
                    exception.getLineNumber() > 0 ? exception.getLineNumber() : null,
                    exception.getColumnNumber() > 0 ? exception.getColumnNumber() : null,
                    severity
            );
        }
    }
}
package com.xmlvalidator.service;

import com.xmlvalidator.model.ValidationResult;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public final class XsdValidatorService {

    public ValidationResult validate(Path xmlPath, Path xsdPath) {
        if (xmlPath == null || !Files.isRegularFile(xmlPath)) {
            return ValidationResult.configurationError("Укажите существующий XML-файл.");
        }
        if (xsdPath == null || !Files.isRegularFile(xsdPath)) {
            return ValidationResult.configurationError("Укажите существующий XSD-файл.");
        }

        Source xmlSource = new StreamSource(xmlPath.toFile());
        xmlSource.setSystemId(xmlPath.toUri().toString());
        return validate(xmlSource, new StreamSource(xsdPath.toFile()));
    }

    public ValidationResult validate(String xmlContent, String xsdContent) {
        if (xmlContent == null || xmlContent.isBlank()) {
            return ValidationResult.configurationError("XML не может быть пустым.");
        }
        if (xsdContent == null || xsdContent.isBlank()) {
            return ValidationResult.configurationError("XSD не может быть пустым.");
        }

        Source xmlSource = streamSource(xmlContent, "inline.xml");
        Source xsdSource = streamSource(xsdContent, "inline.xsd");
        return validate(xmlSource, xsdSource);
    }

    private ValidationResult validate(Source xmlSource, Source xsdSource) {
        try {
            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
            factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file");

            Schema schema = factory.newSchema(xsdSource);
            Validator validator = schema.newValidator();
            validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
            validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file");

            ValidationResult.Builder builder = new ValidationResult.Builder();
            validator.setErrorHandler(new CollectingErrorHandler(builder));
            validator.validate(xmlSource);
            return builder.build();
        } catch (SAXException ex) {
            if (ex instanceof SAXParseException parseEx) {
                return ValidationResult.failure(List.of(new ValidationResult.ValidationError(
                        parseEx.getMessage(),
                        parseEx.getLineNumber() > 0 ? parseEx.getLineNumber() : null,
                        parseEx.getColumnNumber() > 0 ? parseEx.getColumnNumber() : null,
                        "fatal"
                )));
            }
            return ValidationResult.configurationError("Ошибка схемы или XML: " + ex.getMessage());
        } catch (IOException ex) {
            return ValidationResult.configurationError("Ошибка чтения: " + ex.getMessage());
        }
    }

    private static Source streamSource(String content, String systemId) {
        InputStream input = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
        StreamSource source = new StreamSource(input, systemId);
        source.setSystemId(systemId);
        return source;
    }

    private static final class CollectingErrorHandler implements ErrorHandler {
        private final ValidationResult.Builder builder;

        private CollectingErrorHandler(ValidationResult.Builder builder) {
            this.builder = builder;
        }

        @Override
        public void warning(SAXParseException exception) {
            add(exception, "warning");
        }

        @Override
        public void error(SAXParseException exception) {
            add(exception, "error");
        }

        @Override
        public void fatalError(SAXParseException exception) throws SAXException {
            add(exception, "fatal");
            throw exception;
        }

        private void add(SAXParseException exception, String severity) {
            builder.addError(
                    exception.getMessage(),
                    exception.getLineNumber() > 0 ? exception.getLineNumber() : null,
                    exception.getColumnNumber() > 0 ? exception.getColumnNumber() : null,
                    severity
            );
        }
    }
}