Class: Lutaml::Xml::Schema::Xsd::SchemaValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/xml/schema/xsd/schema_validator.rb

Overview

Validates XSD schema documents before parsing

This validator checks that XML content is a valid XSD schema document according to W3C XML Schema Definition Language (XSD) 1.0 or 1.1. It performs pre-parsing validation to ensure the document structure is correct before attempting to parse the schema.

Examples:

Validate an XSD 1.0 schema

validator = Lutaml::Xml::Schema::Xsd::SchemaValidator.new(version: "1.0")
validator.validate(xsd_content)

Validate an XSD 1.1 schema

validator = Lutaml::Xml::Schema::Xsd::SchemaValidator.new(version: "1.1")
validator.validate(xsd_content)

Constant Summary collapse

XSD_NAMESPACE_1_0 =

W3C XML Schema namespace

"http://www.w3.org/2001/XMLSchema"
XSD_NAMESPACE_1_1 =
"http://www.w3.org/2001/XMLSchema"
XSD_NAMESPACE =

They use the same namespace

XSD_NAMESPACE_1_0
XSD_1_1_ELEMENTS =

XSD 1.1 specific elements

%w[
  assert
  assertion
  alternative
  openContent
  defaultOpenContent
].freeze
XSD_1_1_ATTRIBUTES =

XSD 1.1 specific attributes

%w[
  targetNamespace
  defaultAttributes
  xpathDefaultNamespace
].freeze
XSD_1_1_TYPES =

XSD 1.1 specific types

%w[
  anyAtomicType
  dateTimeStamp
  yearMonthDuration
  dayTimeDuration
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(version: "1.0") ⇒ SchemaValidator

Initialize a new SchemaValidator

Parameters:

  • version (String) (defaults to: "1.0")

    XSD version to validate against (“1.0” or “1.1”)

Raises:

  • (ArgumentError)

    if version is not “1.0” or “1.1”



60
61
62
63
64
65
66
67
68
69
# File 'lib/lutaml/xml/schema/xsd/schema_validator.rb', line 60

def initialize(version: "1.0")
  unless %w[
    1.0 1.1
  ].include?(version)
    raise ArgumentError,
          "Invalid XSD version: #{version}. Must be '1.0' or '1.1'"
  end

  @version = version
end

Instance Attribute Details

#versionObject (readonly)

Returns the value of attribute version.



54
55
56
# File 'lib/lutaml/xml/schema/xsd/schema_validator.rb', line 54

def version
  @version
end

Class Method Details

.detect_version(content) ⇒ String

Detect the XSD version from schema content

Parameters:

  • content (String)

    XML content to analyze

Returns:

  • (String)

    Detected version (“1.0” or “1.1”)



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/lutaml/xml/schema/xsd/schema_validator.rb', line 88

def self.detect_version(content)
  doc = ::Nokogiri::XML(content)
  root = doc.root
  return "1.0" unless root

  # Check for XSD 1.1 specific features
  if has_xsd_1_1_features?(doc)
    "1.1"
  else
    # Check version attribute if present
    version_attr = root["version"]
    if version_attr&.start_with?("1.1")
      "1.1"
    else
      "1.0"
    end
  end
rescue ::Nokogiri::XML::SyntaxError
  "1.0" # Default to 1.0 if cannot parse
end

.has_xsd_1_1_features?(doc) ⇒ Boolean

Check if document has XSD 1.1 specific features

Parameters:

  • doc (Nokogiri::XML::Document)

    Parsed XML document

Returns:

  • (Boolean)

    true if XSD 1.1 features are present



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/lutaml/xml/schema/xsd/schema_validator.rb', line 113

def self.has_xsd_1_1_features?(doc)
  # Check for XSD 1.1 specific elements
  XSD_1_1_ELEMENTS.each do |element_name|
    nodes = doc.xpath("//xs:#{element_name}", "xs" => XSD_NAMESPACE)
    return true if nodes.any?

    nodes = doc.xpath("//xsd:#{element_name}", "xsd" => XSD_NAMESPACE)
    return true if nodes.any?
  end

  # Check for XSD 1.1 specific attributes
  root = doc.root
  return false unless root

  XSD_1_1_ATTRIBUTES.each do |attr_name|
    return true if root[attr_name] && attr_name == "defaultAttributes"
    return true if root[attr_name] && attr_name == "xpathDefaultNamespace"
  end

  # Check for XSD 1.1 specific types in type attributes
  type_attrs = doc.xpath("//*[@type]").map { |node| node["type"] }
  type_attrs.each do |type_ref|
    next unless type_ref

    # Extract local name from QName
    local_name = type_ref.include?(":") ? type_ref.split(":").last : type_ref
    return true if XSD_1_1_TYPES.include?(local_name)
  end

  false
end

Instance Method Details

#validate(content) ⇒ true

Validate that content is a valid XSD schema

Parameters:

  • content (String)

    XML content to validate

Returns:

  • (true)

    if validation succeeds

Raises:



76
77
78
79
80
81
82
# File 'lib/lutaml/xml/schema/xsd/schema_validator.rb', line 76

def validate(content)
  validate_xml_syntax(content)
  doc = parse_xml(content)
  validate_schema_root(doc)
  validate_schema_version(doc)
  true
end