Class: SchematronNokogiri::Schema

Inherits:
Object
  • Object
show all
Defined in:
lib/schematron-nokogiri.rb

Constant Summary collapse

ISO_IMPL_DIR =

The location of the ISO schematron implemtation lives

File.join File.dirname(__FILE__), "..", 'iso-schematron-xslt1'
ISO_FILES =

The file names of the compilation stages

['iso_dsdl_include.xsl',
'iso_abstract_expand.xsl',
'iso_svrl_for_xslt1.xsl']
NS_PREFIXES =

Namespace prefix declarations for use in XPaths

{
    'svrl' => 'http://purl.oclc.org/dsdl/svrl'
}

Instance Method Summary collapse

Constructor Details

#initialize(doc) ⇒ Schema

Returns a new instance of Schema.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/schematron-nokogiri.rb', line 20

def initialize(doc)
  schema_doc = doc

  xforms = ISO_FILES.map do |file|

    Dir.chdir(ISO_IMPL_DIR) do
      Nokogiri::XSLT(File.open(file))
    end

  end

  # Compile schematron into xsl that maps to svrl
  @validator_doc = xforms.inject(schema_doc) {
      |xml, xsl| xsl.transform xml
  }
  @validator_xsl = Nokogiri::XSLT(@validator_doc.to_s)
end

Instance Method Details

#node_type(node) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/schematron-nokogiri.rb', line 89

def node_type(node)
  case
    when node.cdata?
      'cdata'
    when node.comment?
      'comment'
    when node.element?
      'element'
    when node.fragment?
      'fragment'
  end
end

#prefixesObject



48
49
50
51
52
53
54
55
# File 'lib/schematron-nokogiri.rb', line 48

def prefixes
  namespaces = {}

  @validator_doc.namespaces.each {
      |k, v| namespaces[k.gsub 'xmlns:', ''] = v
  }
  namespaces
end

#rule_hits(results_doc, instance_doc, rule_type, xpath) ⇒ Object

Look for reported or failed rules of a particular type in the instance doc



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/schematron-nokogiri.rb', line 58

def rule_hits(results_doc, instance_doc, rule_type, xpath)

  results = []

  results_doc.root.xpath(xpath, NS_PREFIXES).each do |hit|
    context_tag = hit
    context_path = nil
    while context_path.nil?
      context_tag = context_tag.previous_sibling
      context_path = context_tag['context']
    end

    context = instance_doc.root.xpath(
        context_path ? '/' + context_path : hit['location'],
        NS_PREFIXES.merge(prefixes)
    ).first

    hit.xpath('svrl:text/text()', NS_PREFIXES).each do |message|
      results << {
          :rule_type => rule_type,
          :type => node_type(context),
          :name => context.name,
          :line => context.line,
          :message => message.content.strip}
    end
  end

  results

end

#validate(instance_doc) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'lib/schematron-nokogiri.rb', line 38

def validate(instance_doc)

  # Validate the xml
  results_doc = @validator_xsl.transform instance_doc

  # compile the errors and log any messages
  rule_hits(results_doc, instance_doc, 'assert', '//svrl:failed-assert') +
      rule_hits(results_doc, instance_doc, 'report', '//svrl:successful-report')
end