/usr/share/doc/libxmlada-doc/html/schema.html is in libxmlada-doc 17.1.2017-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>6. The Schema module — XML/Ada: the XML Library for Ada 18.0w documentation</title>
<link rel="stylesheet" href="_static/sphinxdoc.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '18.0w',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="7. Using the library" href="using.html" />
<link rel="prev" title="5. The DOM module" href="dom.html" />
</head>
<body role="document">
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="using.html" title="7. Using the library"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="dom.html" title="5. The DOM module"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">XML/Ada: the XML Library for Ada 18.0w documentation</a> »</li>
</ul>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="index.html">
<img class="logo" src="_static/adacore_transparent.png" alt="Logo"/>
</a></p>
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">6. The Schema module</a><ul>
<li><a class="reference internal" href="#xml-grammars">6.1. XML Grammars</a></li>
<li><a class="reference internal" href="#xml-schema-syntax">6.2. XML Schema Syntax</a></li>
<li><a class="reference internal" href="#connecting-xml-documents-and-schemas">6.3. Connecting XML documents and schemas</a></li>
<li><a class="reference internal" href="#validating-documents-with-sax">6.4. Validating documents with SAX</a></li>
<li><a class="reference internal" href="#validating-documents-with-dom">6.5. Validating documents with DOM</a></li>
<li><a class="reference internal" href="#unsupported-schema-elements">6.6. Unsupported schema elements</a></li>
<li><a class="reference internal" href="#optimizing-the-parsing-of-grammars">6.7. Optimizing the parsing of grammars</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="dom.html"
title="previous chapter">5. The DOM module</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="using.html"
title="next chapter">7. Using the library</a></p>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/schema.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<div><input type="text" name="q" /></div>
<div><input type="submit" value="Go" /></div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="the-schema-module">
<span id="id1"></span><h1>6. The Schema module<a class="headerlink" href="#the-schema-module" title="Permalink to this headline">¶</a></h1>
<div class="section" id="xml-grammars">
<h2>6.1. XML Grammars<a class="headerlink" href="#xml-grammars" title="Permalink to this headline">¶</a></h2>
<p>There are several steps that applications must go through when they have to use
XML files:</p>
<ul>
<li><p class="first">Make sure the XML file is well-formed.</p>
<p>This is a basic step where we ensure that XML tags are correctly nested, that
closing tags have the same names as the matching opening tags, that attribute
values are quoted,.... This corresponds to a syntactic parser in a compiler.</p>
<p>This step does not depend on the application domain. One file that is
well-formed will always be so, no matter in what context you use it.</p>
</li>
<li><p class="first">Make sure the contents of the XML file is semantically valid.</p>
<p>Depending on the application domain, we must ensure that the content of the
file makes sense. This step is highly application dependent, and a file that
is usable in one application might not be usable in another one.</p>
<p>This is the phase in which the application needs to check whether a given XML
file has all its required attributes, whether the children of an XML tag are
the expected ones, whether the type of the attributes is valid,....</p>
</li>
<li><p class="first">Use the XML file in the application.</p>
<p>This is done through the already-described SAX or DOM parsers</p>
</li>
</ul>
<p>The first phase is mandatory, and necessarily enforced by XML/Ada. You will not
be able to access the contents of the XML file if it isn’t well-formed.</p>
<p>The second phase is provided by the Schema module in XML/Ada. Although such
constraints can be checked at the application level, with ad hoc code, it is
generally easier to maintain a separate file that describes the valid semantic
contents of the file, that maintain specific code when the semantic changes. It
is also difficult not to forget special cases when doing the validating through
a set of <cite>if</cite> statements in the Ada core.</p>
<p>XML provides two ways to describe additional constraints that a file must
satisfy in order to be considered as valid.</p>
<ul>
<li><p class="first">DTD</p>
<p>The Document Type Description is the original way to do this. They come
directly from the ancestor of XML, SGML. All XML parsers must parse the DTD,
and report events if the user is using SAX. However, not all parsers are able
to validate the document against a DTD (XML/Ada doesn’t).</p>
<p>Their use tend to greatly diminish. Among their limitation are a limit
capability to express constraints on the order of tag children, the fact they
the DTD themselves are written in a separate language totally different from
XML, and that users must learn as a result.</p>
</li>
<li><p class="first">XML Schema</p>
<p>The XML schemas are replacing the DTDs. They are written in XML, and provide
an extensive capability to describe what the XML document should look like.
In fact, almost all Ada types can be described in an XML schema, including
range constraints, arrays, records, type inheritance, abstract types,....</p>
<p>It is for instance possible to indicate that the value of a preference, in
our example, must be a string of length 6. Any other length will result in a
validation error.</p>
</li>
</ul>
</div>
<div class="section" id="xml-schema-syntax">
<h2>6.2. XML Schema Syntax<a class="headerlink" href="#xml-schema-syntax" title="Permalink to this headline">¶</a></h2>
<p>The Schema modules provides subprograms and types to parse an XML schema and
validate an XML document with this schema.</p>
<p>This document does not provide a full documentation on the format of XML
Schemas. This is extensive, has several obscure features, which, although
supported by XML/Ada, are of little use in most pratical uses. We refer the
reader to the first part of the XML Schema specification, which is designed as
a tutorial (<a class="reference external" href="http://www.w3.org/TR/xmlschema-0/">http://www.w3.org/TR/xmlschema-0/</a>).</p>
<p>The typical extension for a schema file is <code class="file docutils literal"><span class="pre">.xsd</span></code>.</p>
<p>A schema file must be a valid XML file, and thus start with the usual <cite><?xml
version=”1.0” ?></cite> line. The root node must be named <cite>schema</cite>, and belong to the
namespace (<a class="reference external" href="http://www.w3.org/2001/XMLSchema/">http://www.w3.org/2001/XMLSchema/</a>). The handling of namespaces is fairly
powerful, but also complex. A given XML document might have nodes belonging to
several namespaces, and thus several schema files might have to be loaded, each
defining one of the namespaces.</p>
<p>In the following simple example, we will not define our schema for a specific
namespace, and thus no special attribute is needed for the root node. Thus,
our document will be organized as:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="cp"><?xml version="1.0" ?></span>
<span class="nt"><xsd:schema</span> <span class="na">xmlns:xsd=</span><span class="s">"http://www.w3.org/2001/XMLSchema"</span><span class="nt">></span>
... rest of the description goes here ...
<span class="nt"></xsd:schema></span>
</pre></div>
</div>
<p>An XML schema does not enforce a specific root node in the XML documents it
validates. However, it must define all the valid elements that can be used in
the XML file. This is done through the <cite><element></cite> tag, which takes
one mandatory attribute, the name of the element we are defining.</p>
<p>The contents of the element is then defined in one of two ways:</p>
<ul>
<li><p class="first">Through a <cite>type</cite> attribute.</p>
<p>Schemas come with a number of predefined simple types. A simple type is
such that an element of that type accepts no child node, and that its
contents must satisfy additional constraints (be an integer, a date,
...).</p>
<p>Among the predefined simple type (which are all defined in the namespace
<a class="reference external" href="http://www.w3.org/2001/XMLSchema/">http://www.w3.org/2001/XMLSchema/</a>),
one can find: <cite>string</cite>, <cite>integer</cite>, <cite>byte</cite>, <cite>date</cite>, <cite>time</cite>, <cite>dateTime</cite>,
<cite>boolean</cite>,...</p>
<p>If no additional constraint should be enforced on this simple type when
applied to the element, the type of the element is given through a <cite>type</cite>
attribute, as in:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="nt"><xsd:element</span> <span class="na">name=</span><span class="s">"tag1"</span> <span class="na">type=</span><span class="s">"xsd:string"</span> <span class="nt">/></span>
<span class="nt"><xsd:element</span> <span class="na">name=</span><span class="s">"tag2"</span> <span class="na">type=</span><span class="s">"xsd:boolean"</span> <span class="nt">/></span>
</pre></div>
</div>
<p>which would accept the following XML files:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="nt"><tag1></span>Any string is valid here<span class="nt"></tag1></span>
</pre></div>
</div>
<p>and:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="nt"><tag2></span>true<span class="nt"></tag2></span>
</pre></div>
</div>
<p>but not:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="nt"><tag2></span>String<span class="nt"></tag2></span>
</pre></div>
</div>
<p>As will be described later, it is possible to create new types in XML schema,
which are created with a name. Such new types can also be associated with the
element through the <cite>type</cite> attribute.</p>
</li>
<li><p class="first">Through an inline type definition</p>
<p>If the element must accept child elements, or if a further constraint needs
to be enforced on the list of valid values, one must create the type. As
mentioned above, this can be done by creating a type separately and
referencing it by name, or through an inline type definition.</p>
<p>The syntax is mostly the same in both cases. Schemas distinguish between the
notion of simple types (that accept no child element) and complex types (that
accept child elements, and possibly text value).</p>
<p>To define a simple type, based on string, but that only allows a limited set
of value (similar to an Ada enumeration), one would create a restriction of
the standard string type, as in:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="nt"><xsd:element</span> <span class="na">name=</span><span class="s">"tag3"</span><span class="nt">></span>
<span class="nt"><xsd:simpleType></span>
<span class="nt"><xsd:restriction</span> <span class="na">base=</span><span class="s">"xsd:string"</span><span class="nt">></span>
<span class="nt"><xsd:enumeration</span> <span class="na">value=</span><span class="s">"value1"</span> <span class="nt">/></span>
<span class="nt"><xsd:enumeration</span> <span class="na">value=</span><span class="s">"value2"</span> <span class="nt">/></span>
<span class="nt"></xsd:restriction></span>
<span class="nt"></xsd:simpleType></span>
<span class="nt"></xsd:element></span>
</pre></div>
</div>
<p>Similarly, we could create an integer type whose valid range of values
is between 10 and 20, as in:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="nt"><xsd:element</span> <span class="na">name=</span><span class="s">"tag4"</span><span class="nt">></span>
<span class="nt"><xsd:simpleType></span>
<span class="nt"><xsd:restriction</span> <span class="na">base=</span><span class="s">"xsd:byte"</span><span class="nt">></span>
<span class="nt"><xsd:minInclusive</span> <span class="na">value=</span><span class="s">"10"</span> <span class="nt">/></span>
<span class="nt"><xsd:maxInclusive</span> <span class="na">value=</span><span class="s">"20"</span> <span class="nt">/></span>
<span class="nt"></xsd:restriction></span>
<span class="nt"></xsd:simpleType></span>
<span class="nt"></xsd:element></span>
</pre></div>
</div>
<p>Complex types allow elements to have child nodes, as well as attributes. The
list of valid attributes is created by a set of <cite><xsd:attribute></cite> tags, and
the list of valid child nodes is generally defined either through a
<cite><xsd:choice></cite> or a <cite><xsd:sequence></cite> node (although it is possible to
indicate that any child node is authorized, among other things).</p>
<p><cite><xsd:choice></cite> indicate the children can appear in any order, whereas
<cite><xsd:sequence></cite> enforces a specific order on children.</p>
<p>In both cases, extra attributes can be specified to indicate the number of
times the sequence or choice itself can be repeated, or that each child node
can appear.</p>
<p>For instance, we can indicate that <cite>tag5</cite> accepts between 1 and 4 child
nodes, chosen among <cite>tag6</cite> and <cite>tag7</cite>, but that the latter, if
present, can only appear once. In addition, tag5 accepts one optional
attribute. Note that the type of tag6 and tag7 is here specified through a
<cite>type</cite> attribute, although it could in turn be defined inline:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><xsd:element name="tag5">
<xsd:complexType>
<xsd:choice>
<xsd:element name="tag6" type="xsd:string"
minOccurs="1" maxOccurs="3/>
<xsd:element name="tag7" type="xsd:string" maxOccurs="1" />
</xsd:choice>
<xsd:attribute name="attr" type="xsd:boolean" use="optional" />
</xsd:complexType>
</xsd:element>
</pre></div>
</div>
<p>In the example above, if <cite>tag6</cite> was defined elsewhere in the
schema, we could use a reference to it, instead of duplicating its
type definition, as in:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="nt"><xsd:element</span> <span class="na">ref=</span><span class="s">"tag6"</span> <span class="nt">/></span>
</pre></div>
</div>
<p>If you need an element with no child element (just a string value),
but that accepts attributes, this also must be defined through a
complex type, as in:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="nt"><xsd:element</span> <span class="na">name=</span><span class="s">"tag8"</span> <span class="nt">/></span>
<span class="nt"><xsd:complexType></span>
<span class="nt"><xsd:simpleContent></span>
<span class="nt"><xsd:extension</span> <span class="na">base=</span><span class="s">"xsd:string"</span><span class="nt">></span>
<span class="nt"><xsd:attribute</span> <span class="na">name=</span><span class="s">"attr"</span> <span class="na">type=</span><span class="s">"xsd:boolean"</span> <span class="nt">/></span>
<span class="nt"></xsd:extension></span>
<span class="nt"></xsd:simpleContent></span>
<span class="nt"></xsd:complexType></span>
<span class="nt"></xsd:element></span>
</pre></div>
</div>
</li>
</ul>
<p>As mentioned before, instead of defining inline types, we could explicitly
declare them, and reference them in the element declaration later on:</p>
<div class="highlight-xml"><div class="highlight"><pre><span></span><span class="nt"><xsd:simpleType</span> <span class="na">name=</span><span class="s">"string_of_length_10"</span><span class="nt">></span>
<span class="nt"><xsd:restriction</span> <span class="na">base=</span><span class="s">"xsd:string"</span> <span class="nt">/></span>
<span class="nt"><xsd:length</span> <span class="na">value=</span><span class="s">"10"</span><span class="nt">/></span>
<span class="nt"></xsd:restriction></span>
<span class="nt"></xsd:simpleType></span>
<span class="nt"><xsd:element</span> <span class="na">name=</span><span class="s">"tag9"</span> <span class="na">type=</span><span class="s">"string_of_length_10"</span> <span class="nt">/></span>
</pre></div>
</div>
</div>
<div class="section" id="connecting-xml-documents-and-schemas">
<h2>6.3. Connecting XML documents and schemas<a class="headerlink" href="#connecting-xml-documents-and-schemas" title="Permalink to this headline">¶</a></h2>
<p>There are several ways that XML/Ada uses to find what schema to use when
validating a file.</p>
<ul>
<li><p class="first">Manually creating the grammar.</p>
<p>The schema module contains the package <cite>Schema.Validators</cite> which
allows you to create a grammar by hand. It is very low-level, and it is
likely that you will never need to use it. It is used internally mostly,
and when creating the schema which is used to validate schema files
themselves.</p>
</li>
<li><p class="first">Explicitly parsing a schema file</p>
<p>Parsing a schema file can be done through a call to parse for a reader
derived from <cite>Schema.Schema_Readers.Schema_reader</cite>. As usual, you
call <cite>Parse</cite>, and pass it an input source. As output, you get
access to a grammar, that can then be given to another instance of a
<cite>Schema.Readers.Validating_Reader</cite>.</p>
<p>This technique will generally be used when you need to validate several
XML files with the same grammar: you parse the grammar only once, and
then reuse its instance, instead of reparsing the <code class="file docutils literal"><span class="pre">.xsd</span></code> file every
time:</p>
<div class="highlight-ada"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">with</span> <span class="nn">Ada.Text_IO</span><span class="p">;</span> <span class="kn">use</span> <span class="nn">Ada.Text_IO</span><span class="p">;</span>
<span class="kn">with</span> <span class="nn">Schema.Schema_Readers</span><span class="p">,</span> <span class="n">Schema</span><span class="p">.</span><span class="n">Validators</span><span class="p">,</span> <span class="n">Input_Sources</span><span class="p">.</span><span class="n">File</span><span class="p">;</span>
<span class="kn">use</span> <span class="nn">Schema.Schema_Readers</span><span class="p">,</span> <span class="n">Schema</span><span class="p">.</span><span class="n">Validators</span><span class="p">,</span> <span class="n">Input_Sources</span><span class="p">.</span><span class="n">File</span><span class="p">;</span>
<span class="kd">procedure</span> <span class="nf">SchemaExample2</span> <span class="kr">is</span>
<span class="n">Grammar</span> <span class="p">:</span> <span class="n">XML_Grammar</span><span class="p">;</span>
<span class="n">Schema</span> <span class="p">:</span> <span class="n">Schema_Reader</span><span class="p">;</span>
<span class="n">Read</span> <span class="p">:</span> <span class="n">File_Input</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"file.xsd"</span><span class="p">,</span> <span class="n">Read</span><span class="p">);</span>
<span class="n">Parse</span> <span class="p">(</span><span class="n">Schema</span><span class="p">,</span> <span class="n">Read</span><span class="p">);</span>
<span class="n">Close</span> <span class="p">(</span><span class="n">Read</span><span class="p">);</span>
<span class="n">Grammar</span> <span class="p">:=</span> <span class="n">Get_Grammar</span> <span class="p">(</span><span class="n">Schema</span><span class="p">);</span>
<span class="kr">exception</span>
<span class="kr">when</span> <span class="n">XML_Validation_Error</span> <span class="p">|</span> <span class="n">XML_Not_Implemented</span> <span class="p">=></span>
<span class="n">Put_Line</span> <span class="p">(</span><span class="s">"ERROR: "</span> <span class="o">&</span> <span class="n">Get_Error_Message</span> <span class="p">(</span><span class="n">Schema</span><span class="p">));</span>
<span class="kr">end</span> <span class="nf">SchemaExample2</span><span class="p">;</span>
</pre></div>
</td></tr></table></div>
<p>In the example above, the schema file itself is validated against the
official schema for schema files.</p>
<p>The resulting grammar object is in fact a collection of parsed schema
files, each associated with its own namespace. It can be kept as long as
you need it in your application. Memory will automatically be reclaimed
when no longer needed.</p>
<p>Every time you parse an XML file later on, you must associated the
Grammar with the parser:</p>
<div class="highlight-ada"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kr">declare</span>
<span class="n">Read</span> <span class="p">:</span> <span class="n">File_Input</span><span class="p">;</span>
<span class="n">My_Reader</span> <span class="p">:</span> <span class="n">Validating_Reader</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="n">Set_Grammar</span> <span class="p">(</span><span class="n">My_Reader</span><span class="p">,</span> <span class="n">Grammar</span><span class="p">);</span>
<span class="n">Set_Feature</span> <span class="p">(</span><span class="n">My_Reader</span><span class="p">,</span> <span class="n">Schema_Validation_Feature</span><span class="p">,</span> <span class="kc">True</span><span class="p">);</span>
<span class="n">Open</span> <span class="p">(</span><span class="n">Xml_File</span><span class="p">.</span><span class="kr">all</span><span class="p">,</span> <span class="n">Read</span><span class="p">);</span>
<span class="n">Parse</span> <span class="p">(</span><span class="n">My_Reader</span><span class="p">,</span> <span class="n">Read</span><span class="p">);</span>
<span class="n">Close</span> <span class="p">(</span><span class="n">Read</span><span class="p">);</span>
<span class="kr">exception</span>
<span class="kr">when</span> <span class="n">XML_Validation_Error</span> <span class="p">|</span> <span class="n">XML_Not_Implemented</span> <span class="p">=></span>
<span class="n">Put_Line</span> <span class="p">(</span><span class="s">"ERROR: "</span> <span class="o">&</span> <span class="n">Get_Error_Message</span> <span class="p">(</span><span class="n">My_reader</span><span class="p">));</span>
<span class="kr">end</span><span class="p">;</span>
</pre></div>
</td></tr></table></div>
</li>
<li><p class="first">Implicitly parsing the schema</p>
<p>Two special attributes, defined in the Schema standard, can be used to
indicate, in an XML document itself, that it should be validated with
a specific schema.</p>
<p>These attributes are both defined in a special namespace,
<a class="reference external" href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>.</p>
<ul>
<li><p class="first"><cite>xsi:noNamespaceSchemaLocation</cite></p>
<p>The value of this attribute is the name of a file that contains
the schema to use for elements that are not associated with a
specific namespace.</p>
</li>
<li><p class="first"><cite>xsi:schemaLocation</cite></p>
<p>This attribute is a list of strings, alternatively the prefix of
a namespace and the name of an xsd file to use for that
namespace. For instance, <cite>“ns1 file1.xsd ns2 file2.xsd”</cite>.</p>
</li>
</ul>
<p>When it encounters any of these two attributes, XML/Ada will
automatically parse the corresponding schema files, and use the result
to validate the file.</p>
<p>See the section below on optimizing the parsing of the grammars, as a
way to avoid parsing the same grammar multiple times.</p>
</li>
</ul>
</div>
<div class="section" id="validating-documents-with-sax">
<h2>6.4. Validating documents with SAX<a class="headerlink" href="#validating-documents-with-sax" title="Permalink to this headline">¶</a></h2>
<p>XML/Ada is quite unique in the category of XML parsers, since it allows the
validation of XML files when you are using an event-based parser with SAX.
Most other XML parsers only work on DOM trees.</p>
<p>Basing the validation on SAX is more efficient, since there is no need to read
the whole XML stream (or even the grammar) in memory before starting the
validation, and errors can be reported immediatly.</p>
<p>It also requires less memory to run, and thus can validate large XML
documents.</p>
<p>It also means that even if you are using SAX, and not DOM, you still have
access to the validation features.</p>
<p>Validating a XML document while parsing it is basically done the same as when
using SAX itself. Instead of inheriting from <cite>Sax.Readers.Reader</cite>, your tagged
type must inherit from <cite>Schema.Readers.Validating_Reader</cite>.</p>
<p>As usual, you can still override the predefined primitive operations like
<cite>Start_Element</cite>, <cite>End_Element</cite>, ...</p>
<p>Note the activation of the <cite>Schema_Validation_Feature</cite> feature, without which
no validation takes place:</p>
<div class="highlight-ada"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">with</span> <span class="nn">Ada.Text_IO</span><span class="p">;</span> <span class="kn">use</span> <span class="nn">Ada.Text_IO</span><span class="p">;</span>
<span class="kn">with</span> <span class="nn">Sax.Readers</span><span class="p">;</span> <span class="kn">use</span> <span class="nn">Sax.Readers</span><span class="p">;</span>
<span class="kn">with</span> <span class="nn">Schema.Readers</span><span class="p">;</span> <span class="kn">use</span> <span class="nn">Schema.Readers</span><span class="p">;</span>
<span class="kn">with</span> <span class="nn">Schema.Validators</span><span class="p">;</span>
<span class="kn">with</span> <span class="nn">Input_Sources.File</span><span class="p">;</span> <span class="kn">use</span> <span class="nn">Input_Sources.File</span><span class="p">;</span>
<span class="kd">procedure</span> <span class="nf">SchemaExample</span> <span class="kr">is</span>
<span class="n">Input</span> <span class="p">:</span> <span class="n">File_Input</span><span class="p">;</span>
<span class="n">My_Reader</span> <span class="p">:</span> <span class="n">Validating_Reader</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="n">Set_Public_Id</span> <span class="p">(</span><span class="n">Input</span><span class="p">,</span> <span class="s">"Preferences file"</span><span class="p">);</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"pref.xml"</span><span class="p">,</span> <span class="n">Input</span><span class="p">);</span>
<span class="n">Set_Feature</span> <span class="p">(</span><span class="n">My_Reader</span><span class="p">,</span> <span class="n">Schema_Validation_Feature</span><span class="p">,</span> <span class="kc">True</span><span class="p">);</span>
<span class="n">Parse</span> <span class="p">(</span><span class="n">My_Reader</span><span class="p">,</span> <span class="n">Input</span><span class="p">);</span>
<span class="n">Close</span> <span class="p">(</span><span class="n">Input</span><span class="p">);</span>
<span class="kr">exception</span>
<span class="kr">when</span> <span class="n">Schema</span><span class="p">.</span><span class="n">Validators</span><span class="p">.</span><span class="n">XML_Validation_Error</span> <span class="p">=></span>
<span class="n">Put_Line</span> <span class="p">(</span><span class="s">"ERROR: "</span> <span class="o">&</span> <span class="n">Get_Error_Message</span> <span class="p">(</span><span class="n">My_Reader</span><span class="p">));</span>
<span class="kr">end</span> <span class="nf">SchemaExample</span><span class="p">;</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="section" id="validating-documents-with-dom">
<h2>6.5. Validating documents with DOM<a class="headerlink" href="#validating-documents-with-dom" title="Permalink to this headline">¶</a></h2>
<p>This is very similar to using DOM itself, except the base class of your
reader should be <cite>Schema.Dom_Readers.Tree_Reader</cite>. Going back to the
example described in <a class="reference internal" href="dom.html#using-dom"><span class="std std-ref">Using DOM</span></a>, you would use the following to
validate XML streams before generating the DOM tree.</p>
<div class="highlight-ada"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">with</span> <span class="nn">Input_Sources.File</span><span class="p">;</span> <span class="kn">use</span> <span class="nn">Input_Sources.File</span><span class="p">;</span>
<span class="kn">with</span> <span class="nn">Sax.Readers</span><span class="p">;</span> <span class="kn">use</span> <span class="nn">Sax.Readers</span><span class="p">;</span>
<span class="kn">with</span> <span class="nn">DOM.Core</span><span class="p">;</span> <span class="kn">use</span> <span class="nn">DOM.Core</span><span class="p">;</span>
<span class="kn">with</span> <span class="nn">Schema.Dom_Readers</span><span class="p">;</span> <span class="kn">use</span> <span class="nn">Schema.Dom_Readers</span><span class="p">;</span>
<span class="kd">procedure</span> <span class="nf">DomSchemaExample</span> <span class="kr">is</span>
<span class="n">Input</span> <span class="p">:</span> <span class="n">File_Input</span><span class="p">;</span>
<span class="n">Reader</span> <span class="p">:</span> <span class="n">Schema</span><span class="p">.</span><span class="n">Dom_Readers</span><span class="p">.</span><span class="n">Tree_Reader</span><span class="p">;</span>
<span class="n">Doc</span> <span class="p">:</span> <span class="n">Document</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="n">Set_Public_Id</span> <span class="p">(</span><span class="n">Input</span><span class="p">,</span> <span class="s">"Preferences file"</span><span class="p">);</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"pref_with_xsd.xml"</span><span class="p">,</span> <span class="n">Input</span><span class="p">);</span>
<span class="n">Set_Feature</span> <span class="p">(</span><span class="n">Reader</span><span class="p">,</span> <span class="n">Validation_Feature</span><span class="p">,</span> <span class="kc">False</span><span class="p">);</span>
<span class="n">Parse</span> <span class="p">(</span><span class="n">Reader</span><span class="p">,</span> <span class="n">Input</span><span class="p">);</span>
<span class="n">Close</span> <span class="p">(</span><span class="n">Input</span><span class="p">);</span>
<span class="n">Doc</span> <span class="p">:=</span> <span class="n">Get_Tree</span> <span class="p">(</span><span class="n">Reader</span><span class="p">);</span>
<span class="n">Free</span> <span class="p">(</span><span class="n">Reader</span><span class="p">);</span>
<span class="kr">end</span> <span class="nf">DomSchemaExample</span><span class="p">;</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="section" id="unsupported-schema-elements">
<h2>6.6. Unsupported schema elements<a class="headerlink" href="#unsupported-schema-elements" title="Permalink to this headline">¶</a></h2>
<p>Not all aspects of XML schemas are supported by XML/Ada.
In particular, it does not currently support XPath, so any part of the
schema that is related to XPath expressions (for instance <cite><xsd:key></cite>
and <cite><xsd:unique></cite>) are not supported currently.</p>
</div>
<div class="section" id="optimizing-the-parsing-of-grammars">
<h2>6.7. Optimizing the parsing of grammars<a class="headerlink" href="#optimizing-the-parsing-of-grammars" title="Permalink to this headline">¶</a></h2>
<p>It is often the case that a given <code class="file docutils literal"><span class="pre">.xsd</span></code> file will be reused multiple
times to validate XML documents. In such case, you do not want to parse the
file multiple times, but instead reuse an already existing <cite>XML_Grammar</cite>
object. Of course, this is a tradeoff between memory used to keep the
grammar in memory, and the time it would take to reparse the grammar.</p>
<p>This is easily done when you have a single <code class="file docutils literal"><span class="pre">.xsd</span></code> file to reuse
for all the XML files. Simply call <cite>Set_Grammar</cite> on the parser before
you parse the file, as in:</p>
<div class="highlight-ada"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kr">declare</span>
<span class="no">G</span> <span class="p">:</span> <span class="kr">constant</span> <span class="n">XML_Grammar</span> <span class="p">:=</span> <span class="p">...;</span> <span class="c1">-- parsed earlier</span>
<span class="n">R</span> <span class="p">:</span> <span class="n">Validating_Reader</span><span class="p">;</span>
<span class="n">F</span> <span class="p">:</span> <span class="n">File_Input</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="n">R</span><span class="p">.</span><span class="n">Set_Grammar</span> <span class="p">(</span><span class="n">G</span><span class="p">);</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"file.xml"</span><span class="p">,</span> <span class="n">F</span><span class="p">);</span>
<span class="n">R</span><span class="p">.</span><span class="n">Parse</span> <span class="p">(</span><span class="n">F</span><span class="p">);</span>
<span class="n">Close</span> <span class="p">(</span><span class="n">F</span><span class="p">);</span>
<span class="p">...;</span> <span class="c1">-- Do something with the resulting tree</span>
<span class="kr">end</span><span class="p">;</span>
</pre></div>
</td></tr></table></div>
<p>The second use case is a bit more complex: you have several XSD files to
parse, and the XML files will need either of these. If you are using
namespaces, there is nothing special to do, and the same code as above
applies: you can simply parse each of the XSD file into the same
XML_Grammar, and then use that grammar to parse all the XML files,
as in:</p>
<div class="highlight-ada"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kr">declare</span>
<span class="n">G</span> <span class="p">:</span> <span class="n">XML_Grammar</span><span class="p">;</span>
<span class="n">S</span> <span class="p">:</span> <span class="n">Schema_Reader</span><span class="p">;</span>
<span class="n">F</span> <span class="p">:</span> <span class="n">File_Input</span><span class="p">;</span>
<span class="n">R</span> <span class="p">:</span> <span class="n">Validating_Reader</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"grammar1.xsd"</span><span class="p">,</span> <span class="n">F</span><span class="p">);</span>
<span class="n">S</span><span class="p">.</span><span class="n">Parse</span> <span class="p">(</span><span class="n">F</span><span class="p">);</span>
<span class="n">F</span><span class="p">.</span><span class="n">Close</span><span class="p">;</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"grammar2.xsd"</span><span class="p">,</span> <span class="n">F</span><span class="p">);</span>
<span class="n">S</span><span class="p">.</span><span class="n">Parse</span> <span class="p">(</span><span class="n">F</span><span class="p">);</span>
<span class="n">F</span><span class="p">.</span><span class="n">Close</span><span class="p">;</span>
<span class="n">G</span> <span class="p">:=</span> <span class="n">S</span><span class="p">.</span><span class="n">Get_Grammar</span><span class="p">;</span>
<span class="n">R</span><span class="p">.</span><span class="n">Set_Grammar</span> <span class="p">(</span><span class="n">G</span><span class="p">);</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"file.xml"</span><span class="p">,</span> <span class="n">F</span><span class="p">);</span>
<span class="n">R</span><span class="p">.</span><span class="n">Parse</span> <span class="p">(</span><span class="n">F</span><span class="p">);</span>
<span class="n">F</span><span class="p">.</span><span class="n">Close</span><span class="p">;</span>
<span class="kr">end</span><span class="p">;</span>
</pre></div>
</td></tr></table></div>
<p>If however you are not using namespaces, you cannot use this technics, since
the grammar from the various XSD files would end up mixed up, and validation
will most likely fail. So instead you need to have one <cite>XML_Grammar</cite> per
XSD file, and then set the grammar on the reader dynamically. A full
example is given in the XML/Ada source distribution, in
<code class="file docutils literal"><span class="pre">tests/schema/multiple_xsd</span></code>. Here is an overview.</p>
<p>We first need to parse each of the XSD files into its own grammar:</p>
<div class="highlight-ada"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kr">declare</span>
<span class="n">Symbols</span> <span class="p">:</span> <span class="n">Symbol_Table</span><span class="p">;</span>
<span class="n">G1</span><span class="p">,</span> <span class="n">G2</span> <span class="p">:</span> <span class="n">XML_Grammar</span><span class="p">;</span>
<span class="n">S</span> <span class="p">:</span> <span class="n">Schema_Grammar</span><span class="p">;</span>
<span class="n">F</span> <span class="p">:</span> <span class="n">File_Input</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="c1">-- Since we are going to reuse grammars, we need to ensure their</span>
<span class="c1">-- symbol tables (where internal strings are stored) across all</span>
<span class="c1">-- involved parsers).</span>
<span class="n">Symbols</span> <span class="p">:=</span> <span class="n">Allocate</span><span class="p">;</span>
<span class="n">S</span><span class="p">.</span><span class="n">Set_Symbol_Table</span> <span class="p">(</span><span class="n">Symbols</span><span class="p">);</span>
<span class="c1">-- Now we can parse each of the XSD file</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"algo1.xsd"</span><span class="p">,</span> <span class="n">F</span><span class="p">);</span>
<span class="n">S</span><span class="p">.</span><span class="n">Parse</span> <span class="p">(</span><span class="n">F</span><span class="p">);</span>
<span class="n">F</span><span class="p">.</span><span class="n">Close</span><span class="p">;</span>
<span class="n">G1</span> <span class="p">:=</span> <span class="n">S</span><span class="p">.</span><span class="n">Get_Grammar</span><span class="p">;</span>
<span class="n">S</span><span class="p">.</span><span class="n">Set_Grammar</span> <span class="p">(</span><span class="n">No_Grammar</span><span class="p">);</span> <span class="c1">-- reset</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"algo2.xsd"</span><span class="p">,</span> <span class="n">F</span><span class="p">);</span>
<span class="n">S</span><span class="p">.</span><span class="n">Parse</span> <span class="p">(</span><span class="n">F</span><span class="p">);</span>
<span class="n">F</span><span class="p">.</span><span class="n">Close</span><span class="p">;</span>
<span class="n">G2</span> <span class="p">:=</span> <span class="n">S</span><span class="p">.</span><span class="n">Get_Grammar</span><span class="p">;</span>
<span class="kr">end</span><span class="p">;</span>
</pre></div>
</td></tr></table></div>
<p>We then need to create a custom validating reader, which knows how to set
the grammar based on its name. This is done by overriding one of the
primitive operations of the parser:</p>
<div class="highlight-ada"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kr">declare</span>
<span class="kd">type</span> <span class="kt">My_Reader</span> <span class="kr">is</span> <span class="kr">new</span> <span class="n">Validating_Reader</span> <span class="kr">with</span> <span class="kr">null record</span><span class="p">;</span>
<span class="kr">overriding</span> <span class="kd">procedure</span> <span class="nf">Parse_Grammar</span>
<span class="p">(</span><span class="nv">Self</span> <span class="p">: </span><span class="nv">not</span> <span class="nv">null</span> <span class="nv">access</span> <span class="nv">Reader_With_Preloaded_XSD</span><span class="p">;</span>
<span class="nv">URI</span><span class="p">,</span> <span class="nv">Xsd_File</span> <span class="p">: </span><span class="nv">Sax</span><span class="p">.</span><span class="nv">Symbols</span><span class="p">.</span><span class="nv">Symbol</span><span class="p">;</span>
<span class="nv">Do_Create_NFA</span> <span class="p">: </span><span class="nv">Boolean</span> <span class="p">:=</span> <span class="nv">True</span><span class="p">)</span> <span class="kr">is</span>
<span class="kr">begin</span>
<span class="kr">if</span> <span class="n">Xsd_File</span> <span class="o">=</span> <span class="s">"algo1.xsd"</span> <span class="kr">then</span>
<span class="n">Self</span><span class="p">.</span><span class="n">Set_Grammar</span> <span class="p">(</span><span class="n">G1</span><span class="p">);</span>
<span class="kr">elsif</span> <span class="n">Xsd_File</span> <span class="o">=</span> <span class="s">"algo2.xsd"</span> <span class="kr">then</span>
<span class="n">Self</span><span class="p">.</span><span class="n">Set_Grammar</span> <span class="p">(</span><span class="n">G2</span><span class="p">);</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">end</span> <span class="nf">Parse_Grammar</span><span class="p">;</span>
<span class="n">R</span> <span class="p">:</span> <span class="n">My_Reader</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="c1">-- Also share the same symbol table</span>
<span class="n">R</span><span class="p">.</span><span class="n">Set_Symbol_Table</span> <span class="p">(</span><span class="n">Symbols</span><span class="p">);</span>
<span class="n">R</span><span class="p">.</span><span class="n">Set_Feature</span> <span class="p">(</span><span class="n">Schema_Validation_Feature</span><span class="p">,</span> <span class="kc">True</span><span class="p">);</span>
<span class="n">Open</span> <span class="p">(</span><span class="s">"test1.xml"</span><span class="p">,</span> <span class="n">F</span><span class="p">);</span>
<span class="n">R</span><span class="p">.</span><span class="n">Parse</span> <span class="p">(</span><span class="n">F</span><span class="p">);</span>
<span class="n">F</span><span class="p">.</span><span class="n">Close</span><span class="p">;</span>
<span class="kr">end</span><span class="p">;</span>
</pre></div>
</td></tr></table></div>
<p>Where for instance <code class="file docutils literal"><span class="pre">test1.xml</span></code> contains:</p>
<div class="highlight-ada"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5</pre></div></td><td class="code"><div class="highlight"><pre><span></span><?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="algo1.xsd">
<child>102</child>
</root>
</pre></div>
</td></tr></table></div>
</div>
</div>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="using.html" title="7. Using the library"
>next</a> |</li>
<li class="right" >
<a href="dom.html" title="5. The DOM module"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">XML/Ada: the XML Library for Ada 18.0w documentation</a> »</li>
</ul>
</div>
<div class="footer" role="contentinfo">
© Copyright 2003-2017, AdaCore.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.5.6.
</div>
</body>
</html>
|