schematron-wrapper 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ require 'schematron/version'
2
+ require 'schematron/utils'
3
+ require 'schematron/xslt2'
4
+
5
+ module Schematron
6
+ end
@@ -0,0 +1,29 @@
1
+ require 'tempfile'
2
+
3
+ module Schematron
4
+ module Utils
5
+ def create_temp_file(content, &block)
6
+ temp_file = Tempfile.new('temp_file')
7
+ temp_file.write(content)
8
+ temp_file.rewind
9
+
10
+ begin
11
+ block.call(temp_file)
12
+ ensure
13
+ temp_file.close
14
+ temp_file.unlink
15
+ end
16
+ end
17
+
18
+ def get_attribute_value(element, xpath)
19
+ result = ''
20
+ attributes = element.xpath(xpath)
21
+
22
+ if attributes.size > 0
23
+ result = attributes.first.value
24
+ end
25
+
26
+ result
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,4 @@
1
+ module Schematron
2
+ VERSION = '1.0.0'
3
+ end
4
+
@@ -0,0 +1,71 @@
1
+ require 'nokogiri'
2
+
3
+ module Schematron
4
+ module XSLT2
5
+ extend Schematron::Utils
6
+
7
+ ISO_IMPL_DIR = File.join(File.dirname(__FILE__), '../..', 'iso-schematron-xslt2')
8
+ DSDL_INCLUDES_PATH = File.join(ISO_IMPL_DIR, 'iso_dsdl_include.xsl')
9
+ ABSTRACT_EXPAND_PATH = File.join(ISO_IMPL_DIR, 'iso_abstract_expand.xsl')
10
+ SVRL_FOR_XSLT2_PATH = File.join(ISO_IMPL_DIR, 'iso_svrl_for_xslt2.xsl')
11
+ EXE_PATH = File.join(File.dirname(__FILE__), '../..', 'bin/saxon9he.jar')
12
+
13
+ def self.compile(schematron)
14
+ temp_schematron = process_includes(schematron)
15
+ temp_schematron = expand_abstract_patterns(temp_schematron)
16
+
17
+ create_stylesheet(temp_schematron)
18
+ end
19
+
20
+ def self.validate(stylesheet, xml)
21
+ create_temp_file(stylesheet) do |temp_stylesheet|
22
+ create_temp_file(xml) do |temp_xml|
23
+ execute_transform(temp_stylesheet.path, temp_xml.path)
24
+ end
25
+ end
26
+ end
27
+
28
+ def self.get_errors(validation_result)
29
+ result = []
30
+
31
+ document = Nokogiri::XML(validation_result) do |config|
32
+ config.options = Nokogiri::XML::ParseOptions::NOBLANKS | Nokogiri::XML::ParseOptions::NOENT
33
+ end
34
+
35
+ document.xpath('//svrl:failed-assert').each do |element|
36
+ result.push({message: element.xpath('./svrl:text').text.strip,
37
+ role: get_attribute_value(element, '@role'),
38
+ location: get_attribute_value(element, '@location')})
39
+ end
40
+
41
+ result
42
+ end
43
+
44
+ private
45
+
46
+ def self.process_includes(content_to_transform)
47
+ create_temp_file(content_to_transform) { |temp_file| execute_transform(DSDL_INCLUDES_PATH, temp_file.path) }
48
+ end
49
+
50
+ def self.expand_abstract_patterns(content_to_transform)
51
+ create_temp_file(content_to_transform) { |temp_file| execute_transform(ABSTRACT_EXPAND_PATH, temp_file.path) }
52
+ end
53
+
54
+ def self.create_stylesheet(content_to_transform)
55
+ create_temp_file(content_to_transform) { |temp_file| execute_transform(SVRL_FOR_XSLT2_PATH, temp_file.path, true) }
56
+ end
57
+
58
+ def self.execute_transform(stylesheet, schema, allow_foreign = false)
59
+ cmd = "java -cp #{EXE_PATH} net.sf.saxon.Transform"
60
+
61
+ cmd << " -xsl:#{stylesheet}"
62
+ cmd << " -s:#{schema}"
63
+
64
+ if allow_foreign
65
+ cmd << ' allow-foreign=true'
66
+ end
67
+
68
+ %x{#{cmd}}
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'schematron/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'schematron-wrapper'
8
+ spec.version = Schematron::VERSION
9
+
10
+ spec.authors = ['AgileFreaks']
11
+ spec.email = ['office@agilefreaks.com']
12
+ spec.description = 'A ruby gem that wrappers various schematron implementations so they can be easily used in ruby'
13
+
14
+ spec.homepage = 'https://github.com/Agilefreaks/schematron-wrapper'
15
+ spec.require_paths = ['lib']
16
+ spec.rubygems_version = '1.0.0'
17
+ spec.summary = 'Schematron XSLT 2.0 validator using Saxon9-HE'
18
+
19
+ spec.license = 'Mozilla Public License, version 2.0'
20
+ spec.files = `git ls-files -z`.split("\x0")
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+
24
+ spec.add_development_dependency 'nokogiri', '~> 1.6'
25
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Schematron::XSLT2 do
4
+ SAMPLES_DIR = File.expand_path('../../../../spec/support/samples', __FILE__)
5
+
6
+ describe 'compile' do
7
+ subject { Schematron::XSLT2.compile(input_file) }
8
+
9
+ context 'parameter is schematron' do
10
+ let(:input_file) { File.read(File.join(SAMPLES_DIR, 'initial.sch')) }
11
+
12
+ it { should eq File.read(File.join(SAMPLES_DIR, 'compiled.xsl')) }
13
+ end
14
+ end
15
+
16
+ describe 'validate' do
17
+ let(:stylesheet_file) { File.read(File.join(SAMPLES_DIR, 'compiled.xsl')) }
18
+ let(:target_xml) { File.read(File.join(SAMPLES_DIR, 'target.xml')) }
19
+
20
+ subject { Schematron::XSLT2.validate(stylesheet_file, target_xml).gsub(/"file[^"]*/, '').gsub(/[\s]/, '') }
21
+
22
+ it { should == File.read(File.join(SAMPLES_DIR, 'validation_result.xml')).gsub(/"file[^"]*/, '').gsub(/[\s]/, '') }
23
+ end
24
+
25
+ describe 'get_errors' do
26
+ subject { Schematron::XSLT2.get_errors(validation_result) }
27
+
28
+ context 'validation result has errors' do
29
+ let(:validation_result) { File.read(File.join(SAMPLES_DIR, 'validation_result.xml')) }
30
+
31
+ its(:size) { should eq 2 }
32
+
33
+ its(:first) {
34
+ should include(
35
+ message: 'ePatient.13 - Gender is 9906001 (Female), but eHistory.18 - Pregnancy is 3118011 while it must be 3118003 (Possible, Uncomfirmed).',
36
+ location: "/*:EMSDataSet[namespace-uri()='http://www.nemsis.org'][1]/*:Header[namespace-uri()='http://www.nemsis.org'][1]/*:PatientCareReport[namespace-uri()='http://www.nemsis.org'][1]",
37
+ role: '[FATAL]'
38
+ )
39
+ }
40
+
41
+ its(:last) {
42
+ should include(
43
+ message: 'eTimes.03 - Unit Notified by Dispatch Date/Time 2013-10-02T14:00:50+07:00 should be before eTimes.13 - Unit Back in Service Date/Time 2013-10-02T14:00:50+07:00.',
44
+ location: "/*:EMSDataSet[namespace-uri()='http://www.nemsis.org'][1]/*:Header[namespace-uri()='http://www.nemsis.org'][1]/*:PatientCareReport[namespace-uri()='http://www.nemsis.org'][1]/*:eTimes[namespace-uri()='http://www.nemsis.org'][1]",
45
+ role: '[FATAL]'
46
+ )
47
+ }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ require 'schematron'
2
+ require 'rspec'
3
+
4
+ Dir[File.dirname(__FILE__)+('/support/**/*.rb')].each { |f| require f }
@@ -0,0 +1,334 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema"
3
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
4
+ xmlns:saxon="http://saxon.sf.net/"
5
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
6
+ xmlns:schold="http://www.ascc.net/xml/schematron"
7
+ xmlns:iso="http://purl.oclc.org/dsdl/schematron"
8
+ xmlns:xhtml="http://www.w3.org/1999/xhtml"
9
+ xmlns:nem="http://www.nemsis.org"
10
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
11
+ xmlns:fct="localFunctions"
12
+ version="2.0"><!--Implementers: please note that overriding process-prolog or process-root is
13
+ the preferred method for meta-stylesheets to use where possible. -->
14
+ <xsl:param name="archiveDirParameter"/>
15
+ <xsl:param name="archiveNameParameter"/>
16
+ <xsl:param name="fileNameParameter"/>
17
+ <xsl:param name="fileDirParameter"/>
18
+ <xsl:variable name="document-uri">
19
+ <xsl:value-of select="document-uri(/)"/>
20
+ </xsl:variable>
21
+
22
+ <!--PHASES-->
23
+
24
+
25
+ <!--PROLOG-->
26
+ <xsl:output xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
27
+ method="xml"
28
+ omit-xml-declaration="no"
29
+ standalone="yes"
30
+ indent="yes"/>
31
+
32
+ <!--XSD TYPES FOR XSLT2-->
33
+
34
+
35
+ <!--KEYS AND FUNCTIONS-->
36
+
37
+
38
+ <!--DEFAULT RULES-->
39
+
40
+
41
+ <!--MODE: SCHEMATRON-SELECT-FULL-PATH-->
42
+ <!--This mode can be used to generate an ugly though full XPath for locators-->
43
+ <xsl:template match="*" mode="schematron-select-full-path">
44
+ <xsl:apply-templates select="." mode="schematron-get-full-path"/>
45
+ </xsl:template>
46
+
47
+ <!--MODE: SCHEMATRON-FULL-PATH-->
48
+ <!--This mode can be used to generate an ugly though full XPath for locators-->
49
+ <xsl:template match="*" mode="schematron-get-full-path">
50
+ <xsl:apply-templates select="parent::*" mode="schematron-get-full-path"/>
51
+ <xsl:text>/</xsl:text>
52
+ <xsl:choose>
53
+ <xsl:when test="namespace-uri()=''">
54
+ <xsl:value-of select="name()"/>
55
+ </xsl:when>
56
+ <xsl:otherwise>
57
+ <xsl:text>*:</xsl:text>
58
+ <xsl:value-of select="local-name()"/>
59
+ <xsl:text>[namespace-uri()='</xsl:text>
60
+ <xsl:value-of select="namespace-uri()"/>
61
+ <xsl:text>']</xsl:text>
62
+ </xsl:otherwise>
63
+ </xsl:choose>
64
+ <xsl:variable name="preceding"
65
+ select="count(preceding-sibling::*[local-name()=local-name(current()) and namespace-uri() = namespace-uri(current())])"/>
66
+ <xsl:text>[</xsl:text>
67
+ <xsl:value-of select="1+ $preceding"/>
68
+ <xsl:text>]</xsl:text>
69
+ </xsl:template>
70
+ <xsl:template match="@*" mode="schematron-get-full-path">
71
+ <xsl:apply-templates select="parent::*" mode="schematron-get-full-path"/>
72
+ <xsl:text>/</xsl:text>
73
+ <xsl:choose>
74
+ <xsl:when test="namespace-uri()=''">@<xsl:value-of select="name()"/>
75
+ </xsl:when>
76
+ <xsl:otherwise>
77
+ <xsl:text>@*[local-name()='</xsl:text>
78
+ <xsl:value-of select="local-name()"/>
79
+ <xsl:text>' and namespace-uri()='</xsl:text>
80
+ <xsl:value-of select="namespace-uri()"/>
81
+ <xsl:text>']</xsl:text>
82
+ </xsl:otherwise>
83
+ </xsl:choose>
84
+ </xsl:template>
85
+
86
+ <!--MODE: SCHEMATRON-FULL-PATH-2-->
87
+ <!--This mode can be used to generate prefixed XPath for humans-->
88
+ <xsl:template match="node() | @*" mode="schematron-get-full-path-2">
89
+ <xsl:for-each select="ancestor-or-self::*">
90
+ <xsl:text>/</xsl:text>
91
+ <xsl:value-of select="name(.)"/>
92
+ <xsl:if test="preceding-sibling::*[name(.)=name(current())]">
93
+ <xsl:text>[</xsl:text>
94
+ <xsl:value-of select="count(preceding-sibling::*[name(.)=name(current())])+1"/>
95
+ <xsl:text>]</xsl:text>
96
+ </xsl:if>
97
+ </xsl:for-each>
98
+ <xsl:if test="not(self::*)">
99
+ <xsl:text/>/@<xsl:value-of select="name(.)"/>
100
+ </xsl:if>
101
+ </xsl:template>
102
+ <!--MODE: SCHEMATRON-FULL-PATH-3-->
103
+ <!--This mode can be used to generate prefixed XPath for humans
104
+ (Top-level element has index)-->
105
+ <xsl:template match="node() | @*" mode="schematron-get-full-path-3">
106
+ <xsl:for-each select="ancestor-or-self::*">
107
+ <xsl:text>/</xsl:text>
108
+ <xsl:value-of select="name(.)"/>
109
+ <xsl:if test="parent::*">
110
+ <xsl:text>[</xsl:text>
111
+ <xsl:value-of select="count(preceding-sibling::*[name(.)=name(current())])+1"/>
112
+ <xsl:text>]</xsl:text>
113
+ </xsl:if>
114
+ </xsl:for-each>
115
+ <xsl:if test="not(self::*)">
116
+ <xsl:text/>/@<xsl:value-of select="name(.)"/>
117
+ </xsl:if>
118
+ </xsl:template>
119
+
120
+ <!--MODE: GENERATE-ID-FROM-PATH -->
121
+ <xsl:template match="/" mode="generate-id-from-path"/>
122
+ <xsl:template match="text()" mode="generate-id-from-path">
123
+ <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
124
+ <xsl:value-of select="concat('.text-', 1+count(preceding-sibling::text()), '-')"/>
125
+ </xsl:template>
126
+ <xsl:template match="comment()" mode="generate-id-from-path">
127
+ <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
128
+ <xsl:value-of select="concat('.comment-', 1+count(preceding-sibling::comment()), '-')"/>
129
+ </xsl:template>
130
+ <xsl:template match="processing-instruction()" mode="generate-id-from-path">
131
+ <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
132
+ <xsl:value-of select="concat('.processing-instruction-', 1+count(preceding-sibling::processing-instruction()), '-')"/>
133
+ </xsl:template>
134
+ <xsl:template match="@*" mode="generate-id-from-path">
135
+ <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
136
+ <xsl:value-of select="concat('.@', name())"/>
137
+ </xsl:template>
138
+ <xsl:template match="*" mode="generate-id-from-path" priority="-0.5">
139
+ <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
140
+ <xsl:text>.</xsl:text>
141
+ <xsl:value-of select="concat('.',name(),'-',1+count(preceding-sibling::*[name()=name(current())]),'-')"/>
142
+ </xsl:template>
143
+
144
+ <!--MODE: GENERATE-ID-2 -->
145
+ <xsl:template match="/" mode="generate-id-2">U</xsl:template>
146
+ <xsl:template match="*" mode="generate-id-2" priority="2">
147
+ <xsl:text>U</xsl:text>
148
+ <xsl:number level="multiple" count="*"/>
149
+ </xsl:template>
150
+ <xsl:template match="node()" mode="generate-id-2">
151
+ <xsl:text>U.</xsl:text>
152
+ <xsl:number level="multiple" count="*"/>
153
+ <xsl:text>n</xsl:text>
154
+ <xsl:number count="node()"/>
155
+ </xsl:template>
156
+ <xsl:template match="@*" mode="generate-id-2">
157
+ <xsl:text>U.</xsl:text>
158
+ <xsl:number level="multiple" count="*"/>
159
+ <xsl:text>_</xsl:text>
160
+ <xsl:value-of select="string-length(local-name(.))"/>
161
+ <xsl:text>_</xsl:text>
162
+ <xsl:value-of select="translate(name(),':','.')"/>
163
+ </xsl:template>
164
+ <!--Strip characters-->
165
+ <xsl:template match="text()" priority="-1"/>
166
+
167
+ <!--SCHEMA SETUP-->
168
+ <xsl:template match="/">
169
+ <svrl:schematron-output xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
170
+ title="NEMSIS Compliance Test ISO Schematron File"
171
+ schemaVersion="">
172
+ <xsl:comment>
173
+ <xsl:value-of select="$archiveDirParameter"/>  
174
+ <xsl:value-of select="$archiveNameParameter"/>  
175
+ <xsl:value-of select="$fileNameParameter"/>  
176
+ <xsl:value-of select="$fileDirParameter"/>
177
+ </xsl:comment>
178
+ <svrl:ns-prefix-in-attribute-values uri="http://www.nemsis.org" prefix="nem"/>
179
+ <svrl:ns-prefix-in-attribute-values uri="http://www.w3.org/1999/XSL/Transform" prefix="xsl"/>
180
+ <svrl:ns-prefix-in-attribute-values uri="http://www.w3.org/2001/XMLSchema-instance" prefix="xsi"/>
181
+ <svrl:ns-prefix-in-attribute-values uri="localFunctions" prefix="fct"/>
182
+ <svrl:active-pattern>
183
+ <xsl:attribute name="document">
184
+ <xsl:value-of select="document-uri(/)"/>
185
+ </xsl:attribute>
186
+ <xsl:attribute name="id">complianceTestStructureRule1</xsl:attribute>
187
+ <xsl:attribute name="name">When ePatient.13 is 9906001, eHistory.18 must be 3118003.</xsl:attribute>
188
+ <xsl:apply-templates/>
189
+ </svrl:active-pattern>
190
+ <xsl:apply-templates select="/" mode="M5"/>
191
+ <svrl:active-pattern>
192
+ <xsl:attribute name="document">
193
+ <xsl:value-of select="document-uri(/)"/>
194
+ </xsl:attribute>
195
+ <xsl:attribute name="id">complianceTestStructureRule2</xsl:attribute>
196
+ <xsl:attribute name="name">eTimes.03 - Unit Notied by Dispatch Date/Time is before eTimes.13 - Unit Back in Service Date/Time</xsl:attribute>
197
+ <xsl:apply-templates/>
198
+ </svrl:active-pattern>
199
+ <xsl:apply-templates select="/" mode="M6"/>
200
+ <svrl:active-pattern>
201
+ <xsl:attribute name="document">
202
+ <xsl:value-of select="document-uri(/)"/>
203
+ </xsl:attribute>
204
+ <xsl:attribute name="id">complianceTestStructureRule3</xsl:attribute>
205
+ <xsl:attribute name="name">eDispatch.01 - Complaint Reported by Dispatch must not be 2301069</xsl:attribute>
206
+ <xsl:apply-templates/>
207
+ </svrl:active-pattern>
208
+ <xsl:apply-templates select="/" mode="M7"/>
209
+ </svrl:schematron-output>
210
+ </xsl:template>
211
+
212
+ <!--SCHEMATRON PATTERNS-->
213
+ <svrl:text xmlns:svrl="http://purl.oclc.org/dsdl/svrl">NEMSIS Compliance Test ISO Schematron File</svrl:text>
214
+
215
+ <!--PATTERN complianceTestStructureRule1When ePatient.13 is 9906001, eHistory.18 must be 3118003.-->
216
+ <svrl:text xmlns:svrl="http://purl.oclc.org/dsdl/svrl">When ePatient.13 is 9906001, eHistory.18 must be 3118003.</svrl:text>
217
+
218
+ <!--RULE -->
219
+ <xsl:template match="nem:Header/nem:PatientCareReport" priority="1000" mode="M5">
220
+ <svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
221
+ context="nem:Header/nem:PatientCareReport"
222
+ role="[FATAL]"/>
223
+ <xsl:variable name="patientCare" select="normalize-space(.)"/>
224
+ <xsl:variable name="ePatient13"
225
+ select="normalize-space(./nem:ePatient/nem:ePatient.13/.)"/>
226
+ <xsl:variable name="eHistory18"
227
+ select="normalize-space(./nem:eHistory/nem:eHistory.18/.)"/>
228
+
229
+ <!--ASSERT [FATAL]-->
230
+ <xsl:choose>
231
+ <xsl:when test="if (number($ePatient13) = 9906001) then (if (number($eHistory18) = 3118003) then true() else false()) else true()"/>
232
+ <xsl:otherwise>
233
+ <svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
234
+ test="if (number($ePatient13) = 9906001) then (if (number($eHistory18) = 3118003) then true() else false()) else true()">
235
+ <xsl:attribute name="role">[FATAL]</xsl:attribute>
236
+ <xsl:attribute name="location">
237
+ <xsl:apply-templates select="." mode="schematron-select-full-path"/>
238
+ </xsl:attribute>
239
+ <svrl:text>
240
+ ePatient.13 - Gender is 9906001 (Female), but eHistory.18 - Pregnancy is <xsl:text/>
241
+ <xsl:value-of select="$eHistory18"/>
242
+ <xsl:text/> while it must be 3118003 (Possible, Uncomfirmed).
243
+ </svrl:text>
244
+ </svrl:failed-assert>
245
+ </xsl:otherwise>
246
+ </xsl:choose>
247
+ <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M5"/>
248
+ </xsl:template>
249
+ <xsl:template match="text()" priority="-1" mode="M5"/>
250
+ <xsl:template match="@*|node()" priority="-2" mode="M5">
251
+ <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M5"/>
252
+ </xsl:template>
253
+
254
+ <!--PATTERN complianceTestStructureRule2eTimes.03 - Unit Notied by Dispatch Date/Time is before eTimes.13 - Unit Back in Service Date/Time-->
255
+ <svrl:text xmlns:svrl="http://purl.oclc.org/dsdl/svrl">eTimes.03 - Unit Notied by Dispatch Date/Time is before eTimes.13 - Unit Back in Service Date/Time</svrl:text>
256
+
257
+ <!--RULE -->
258
+ <xsl:template match="nem:Header/nem:PatientCareReport/nem:eTimes"
259
+ priority="1000"
260
+ mode="M6">
261
+ <svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
262
+ context="nem:Header/nem:PatientCareReport/nem:eTimes"
263
+ role="[FATAL]"/>
264
+ <xsl:variable name="eTimes" select="normalize-space(.)"/>
265
+ <xsl:variable name="eTimes03" select="normalize-space(./nem:eTimes.03/.)"/>
266
+ <xsl:variable name="eTimes13" select="normalize-space(./nem:eTimes.13/.)"/>
267
+ <xsl:variable name="eTimes03All"
268
+ select="normalize-space(concat(substring($eTimes03,1,4), substring($eTimes03,6,2), substring($eTimes03,9,2), substring($eTimes03,12,2), substring($eTimes03,15,2), substring($eTimes03,18,2)))"/>
269
+ <xsl:variable name="eTimes13All"
270
+ select="normalize-space(concat(substring($eTimes13,1,4), substring($eTimes13,6,2), substring($eTimes13,9,2), substring($eTimes13,12,2), substring($eTimes13,15,2), substring($eTimes13,18,2)))"/>
271
+
272
+ <!--ASSERT [FATAL]-->
273
+ <xsl:choose>
274
+ <xsl:when test=" if (number($eTimes03All) &lt; number($eTimes13All)) then true() else false() "/>
275
+ <xsl:otherwise>
276
+ <svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
277
+ test="if (number($eTimes03All) &lt; number($eTimes13All)) then true() else false()">
278
+ <xsl:attribute name="role">[FATAL]</xsl:attribute>
279
+ <xsl:attribute name="location">
280
+ <xsl:apply-templates select="." mode="schematron-select-full-path"/>
281
+ </xsl:attribute>
282
+ <svrl:text>
283
+ eTimes.03 - Unit Notified by Dispatch Date/Time <xsl:text/>
284
+ <xsl:value-of select="$eTimes03"/>
285
+ <xsl:text/> should be before eTimes.13 - Unit Back in Service Date/Time <xsl:text/>
286
+ <xsl:value-of select="$eTimes13"/>
287
+ <xsl:text/>.
288
+ </svrl:text>
289
+ </svrl:failed-assert>
290
+ </xsl:otherwise>
291
+ </xsl:choose>
292
+ <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M6"/>
293
+ </xsl:template>
294
+ <xsl:template match="text()" priority="-1" mode="M6"/>
295
+ <xsl:template match="@*|node()" priority="-2" mode="M6">
296
+ <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M6"/>
297
+ </xsl:template>
298
+
299
+ <!--PATTERN complianceTestStructureRule3eDispatch.01 - Complaint Reported by Dispatch must not be 2301069-->
300
+ <svrl:text xmlns:svrl="http://purl.oclc.org/dsdl/svrl">eDispatch.01 - Complaint Reported by Dispatch must not be 2301069</svrl:text>
301
+
302
+ <!--RULE -->
303
+ <xsl:template match="nem:Header/nem:PatientCareReport/nem:eDispatch"
304
+ priority="1000"
305
+ mode="M7">
306
+ <svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
307
+ context="nem:Header/nem:PatientCareReport/nem:eDispatch"
308
+ role="[FATAL]"/>
309
+ <xsl:variable name="eDispatch" select="normalize-space(.)"/>
310
+ <xsl:variable name="eDispatch01" select="normalize-space(./nem:eDispatch.01/.)"/>
311
+
312
+ <!--ASSERT [FATAL]-->
313
+ <xsl:choose>
314
+ <xsl:when test="if (number($eDispatch01) = 2301007) then false() else true()"/>
315
+ <xsl:otherwise>
316
+ <svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
317
+ test="if (number($eDispatch01) = 2301007) then false() else true()">
318
+ <xsl:attribute name="role">[FATAL]</xsl:attribute>
319
+ <xsl:attribute name="location">
320
+ <xsl:apply-templates select="." mode="schematron-select-full-path"/>
321
+ </xsl:attribute>
322
+ <svrl:text>
323
+ eDispatch.01 - Complaint Reported by Dispatch must NOT be 2301007.
324
+ </svrl:text>
325
+ </svrl:failed-assert>
326
+ </xsl:otherwise>
327
+ </xsl:choose>
328
+ <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M7"/>
329
+ </xsl:template>
330
+ <xsl:template match="text()" priority="-1" mode="M7"/>
331
+ <xsl:template match="@*|node()" priority="-2" mode="M7">
332
+ <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M7"/>
333
+ </xsl:template>
334
+ </xsl:stylesheet>