Repository: symfony/symfony
File: src/Symfony/Component/Validator/Constraints/XmlValidator.php (PHP)

Code before:

        if (!\is_scalar($value) && !$value instanceof \Stringable) {
            throw new UnexpectedValueException($value, 'string');
        }

        $value = (string) $value;
        $previousUseErrors = libxml_use_internal_errors(true);

        try {
            // First, check if XML is well-formed
            if (false === $doc = simplexml_load_string($value)) {
                $this->context->buildViolation($constraint->formatMessage)
                    ->setParameter('{{ value }}', $this->formatValue($value))
                    ->setCode(Xml::INVALID_XML_ERROR)
                    ->addViolation();

                libxml_clear_errors();

                return;
            }

            // Second, validate against XML Schema if schemaPath provided
            if ($constraint->schemaPath) {
                $dom = \dom_import_simplexml($doc)->ownerDocument;

                if (!$dom->schemaValidate($constraint->schemaPath, $constraint->schemaFlags)) {
                    $errors = libxml_get_errors();
                    libxml_clear_errors();

                    foreach ($errors as $error) {
                        $this->context->buildViolation($constraint->schemaMessage)
                            ->setParameter('{{ error }}', $error->message)
                            ->setParameter('{{ line }}', $error->line)
                            ->setCode(Xml::INVALID_XML_ERROR)
                            ->addViolation();
                    }
                }
            }
        } finally {
            libxml_use_internal_errors($previousUseErrors);
        }
    }
}


Review comment (suggestion):
If the XSD file itself is invalid, this reports as contraint violation "This value is not conform to the expected XSD schema.". This should be a regular exception, that's an issue with the constraint configuration, not the value.

Code after:
        }

        if (!\is_scalar($value) && !$value instanceof \Stringable) {
            throw new UnexpectedValueException($value, 'string');
        }

        $value = (string) $value;
        $previousUseErrors = libxml_use_internal_errors(true);

        try {
            // First, check if XML is well-formed
            if (false === $doc = simplexml_load_string($value)) {
                $this->context->buildViolation($constraint->formatMessage)
                    ->setParameter('{{ value }}', $this->formatValue($value))
                    ->setCode(Xml::INVALID_XML_ERROR)
                    ->addViolation();

                libxml_clear_errors();

                return;
            }

            // Second, validate against XML Schema if schemaPath provided
            if ($schemaPath = $constraint->schemaPath) {
                $dom = dom_import_simplexml($doc)->ownerDocument;
                libxml_clear_errors();
                $schemaPath = realpath($schemaPath) ?: $schemaPath;

                if (@$dom->schemaValidate($schemaPath, $constraint->schemaFlags)) {
                    return;
                }
                $errors = libxml_get_errors();
                libxml_clear_errors();

                foreach ($errors as $error) {
                    if ($schemaPath && (realpath($error->file) ?: $error->file) === $schemaPath) {
                        throw new InvalidArgumentException(\sprintf('The XSD schema file "%s" is not valid.', $schemaPath));
                    }
                    $schemaPath = false;
                    $this->context->buildViolation($constraint->schemaMessage)
                        ->setParameter('{{ error }}', $error->message)
                        ->setParameter('{{ line }}', $error->line)
                        ->setCode(Xml::INVALID_XML_ERROR)
                        ->addViolation();
                }
            }
        } finally {
            libxml_use_internal_errors($previousUseErrors);
        }
    }
}