Index: genlangxml =================================================================== --- genlangxml (revision 0) +++ genlangxml (revision 0) @@ -0,0 +1,302 @@ +#!/usr/bin/perl -s +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id: genlang 14567 2007-09-01 20:54:17Z rasher $ +# +# Copyright (C) 2006 - 2007 by Daniel Stenberg +# + +# binary version for the binary lang file +my $langversion = 4; # 3 was the latest one used in the v1 format + +# A note for future users and readers: The original v1 language system allowed +# the build to create and use a different language than english built-in. We +# removed that feature from our build-system, but the build scripts still had +# the ability. But, starting now, this ability is no longer provided since I +# figured it was boring and unnecessary to write support for now since we +# don't use it anymore. + +use strict; +use warnings; +use encoding 'utf8'; +use XML::LibXML; +# The vars we may receive on the commandline. Or strict mode will kill us dead +use vars qw($p $b $u $e $t $i $o $v); + +if(!$ARGV[0]) { + print < + + -p= + Make the tool create a [prefix].c and [prefix].h file. + + -b= + Make the tool create a binary language (.lng) file named [outfile]. + The use of this option requires that you also use -e, -t and -i. + + -u + Update language file. Given the translated file and the most recent english + file, you\'ll get an updated version sent to stdout. Suitable action to do + when you intend to update a translation. + + -e= + Point out the english (original source) file, to use that as master + language template. Used in combination with -b or -u. + + -t= + Specify which target you want the translations/phrases for. Required when + -b or -p is used. + + The target can in fact be specified as numerous different strings, + separated with colons. This will make genlang to use all the specified + strings when searching for a matching phrase. + + -i= + The target id number, needed for -b. + + -o + Voice mode output. Outputs all id: and voice: lines for the given target! + + -v + Enables verbose (debug) output. +MOO + ; + exit; +} + +# How update works: +# +# 1) scan the english file, keep the whole for each phrase. +# 2) read the translated file, for each end of phrase, compare: +# A) all source strings, if there's any change there should be a comment about +# it output +# B) the desc fields +# +# 3) output the phrase with the comments from above +# 4) check which phrases that the translated version didn't have, and spit out +# the english version of those +# + +my $prefix = $p; +my $binary = $b; +my $update = $u; + +my $english = $e; +my $voiceout = $o; + +my $check = ($binary?1:0) + ($prefix?1:0) + ($update?1:0) + ($voiceout?1:0); + +if($check > 1) { + print "Please use only one of -p, -u, -o and -b\n"; + exit; +} +if(!$check) { + print "Please use at least one of -p, -u, -o and -b\n"; + exit; +} + +if(($binary || $update || $voiceout) && !$english) { + print "Please use -e too when you use -b, -o or -u\n"; + exit; +} + +my $target_id = $i; +if($binary && !$target_id) { + print "Please specify a target id number (with -i)!\n"; + exit; +} + +my $target = $t; +if(!$target && !$update) { + print "Please specify a target (with -t)!\n"; + exit; +} +my $verbose=$v; + +my $input = $ARGV[0]; + +# Figure out what to do +if ($update) { + update($input, $english); +} +elsif ($binary) { + binary($input, $binary, $english, $target, $target_id, $langversion); +} +elsif ($voiceout) { + voiceout($input, $english, $target); +} + +# Function definitions start here + +# This helper function reads in english and input languages +# and returns a mapping of positions in the input language as well as a map of +# language ids to numeric ids +# Both language files are also checked against our language schema +sub readlanguages { + my ($inputfile, $englishfile) = @_; + my %inputidpos; + my %idmap; + my $xmlschema; + my $res; + + $xmlschema = XML::LibXML::Schema->new( location => 'language.xsd' ); + + # Read in inputfile and validate against our schema + $input = XML::LibXML->new->parse_file($inputfile); + $res = eval { $xmlschema->validate($input); }; + # Die and notify if errors occured (not too helpful error messages unfortunately): + die "Error: $inputfile is not a valid languagefile\n" . $@ if $@; + + # Find out where phrases are located in the input tree + my $inputPhrases = $input->getElementsByTagName("phrase"); + for (my $i = 0; $i < $inputPhrases->size(); $i++) { + $inputidpos{$inputPhrases->get_node($i)->getAttribute("id")} = $i; + } + + # Read in English file and alidate against our schema + $english = XML::LibXML->new->parse_file($englishfile); + $res = eval { $xmlschema->validate($english); }; + die "Error: $englishfile is not a valid languagefile\n" . $@ if $@; + + # Make a map of numeric IDs for the phrases - used for binary and .c/.h + # files + my $idcount=0; # counter for lang ID numbers + my $voiceid=0x8000; # counter for voice-only ID numbers + my $englishPhrases = $english->getElementsByTagName("phrase"); + + for (my $i = 0; $i < $englishPhrases->size(); $i++) { + my $numid; + my $id = $englishPhrases->get_node($i)->getAttribute("id"); + if ($id =~ /^VOICE/) { + $numid = $voiceid++; + } + else { + $numid = $idcount++; + } + $idmap{$id} = $numid; + } + + printf("\$input->encoding: %s\n", $input->encoding); + printf("\$input->actualEncoding: %s\n", $input->actualEncoding); +# print($input->getElementsByTagName("phrase")->get_node($inputidpos{'LANG_CATALOG_NO_PLAYLISTS'})->toString(1, 1)."\n"); + printf("Random string: %s\n", $input->getElementsByTagName("phrase")->get_node($inputidpos{'LANG_CATALOG_NO_PLAYLISTS'})->getElementsByTagName("dest")->get_node(0)->getElementsByTagName("target")->get_node(0)->textContent); + + return \($input, $english, %inputidpos, %idmap); +} + +# This helper function picks the correct out of a number or elements, +# by matching the element's name attribute with the given target-string +sub gettarget { + my ($targetElements, $targetstring) = @_; + for (my $i = 0; $i < $targetElements->size(); $i++) { + my $thisTarget = $targetElements->get_node($i)->getAttribute("name"); + for my $test (split(",", $thisTarget)) { + for my $part (split(":", $targetstring)) { + if ($test eq "*" || $test eq $part) { + return $targetElements->get_node($i); + } + } + } + } +} + +# This function updates a given inputfile and writes out the new +# languagefile with notes about missing and/or changed strings +sub update { + my ($inputfile, $englishfile) = @_; + + # Initial tango + my ($input, $english, $inputidpos, $idmap) = readlanguages($inputfile, $englishfile); + bless($input, 'XML::LibXML::Document'); + bless($english, 'XML::LibXML::Document'); + + my $inputPhrases = $input->getElementsByTagName("phrase"); + # Loop through English phrases + my $englishPhrases = $english->getElementsByTagName("phrase"); + for (my $i = 0; $i < $englishPhrases->size(); $i++) { + # Extract the english phrase for good luck + my $englishPhrase = $englishPhrases->get_node($i); + my $id = $englishPhrase->getAttribute("id"); + # Extract the input phrase from the input tree at the location + # we found in the first loop + + # Check for the following cases: + # 1. Phrase is missing entirely + if (!defined($$inputidpos{$id})) { + $englishPhrase->setAttribute("note", "This string was not available in the translation"); + $input->documentElement()->appendChild($englishPhrase); + } + else { + my $inputPhrase = $inputPhrases->get_node($$inputidpos{$id}); + + # 2. Desc differs from the one used when translating + if ($inputPhrase->getAttribute("desc") + ne $englishPhrase->getAttribute("desc")) { + $inputPhrase->setAttribute("note", sprintf("Desc differs: %s -- %s", $inputPhrase->getAttribute("desc"), $englishPhrase->getAttribute("desc"))); + } + + # 3. A + my $englishSources = $englishPhrase->getElementsByTagName("source")->get_node(0)->getElementsByTagName("target"); + for (my $j = 0; $j < $englishSources->size(); $j++) { + } + } + } + print($input->toString(1)); +} + +# This function generates a new binary languagefile +sub binary { + my ($inputfile, $outputfile, $englishfile, $target, $target_id, $langversion) = @_; + + # Initial tango + my ($input, $english, $inputidpos, $idmap) = readlanguages($inputfile, $englishfile); + bless($input, 'XML::LibXML::Document'); + bless($english, 'XML::LibXML::Document'); + + open(OUTF, ">$outputfile") or die("Can't create $outputfile"); + binmode(OUTF, ":utf8"); + printf(OUTF "\x1a%c%c", $langversion, $target_id); # magic lang file header + + # Loop through input phrases and write out the language file with the + # numeric ids from our map + my $inputPhrases = $$input->getElementsByTagName("phrase"); + for (my $i = 0; $i < $inputPhrases->size(); $i++) { + my $phrase = $inputPhrases->get_node($i); + my $numid = $$idmap{$phrase->getAttribute("id")}; + + my $targets = $phrase->getElementsByTagName("dest")->get_node(0)->getElementsByTagName("target"); + my $target = gettarget($targets, $target); + if ($target ne "none") { + printf ("Value of %s (%d): %s\n", $phrase->getAttribute("id"), $numid, $target->textContent); + + printf(OUTF "%c%c%s\x00", ($numid>>8), ($numid&0xff), $target->textContent); + } + } + close(OUTF); +} + +sub voiceout { + my ($inputfile, $englishfile, $target) = @_; + + # Initial tango + my ($input, $english, $inputidpos, $idmap) = readlanguages($inputfile, $englishfile); + bless($input, 'XML::LibXML::Document'); + bless($english, 'XML::LibXML::Document'); + + my $inputPhrases = $$input->getElementsByTagName("phrase"); + for (my $i = 0; $i < $inputPhrases->size(); $i++) { + my $phrase = $inputPhrases->get_node($i); + my $id = $phrase->getAttribute("id"); + my $numid = $$idmap{$id}; + my $targets = $phrase->getElementsByTagName("voice")->get_node(0)->getElementsByTagName("target"); + my $target = gettarget($targets, $target); + my $voice = $target->textContent; + if ($voice ne "none" && length($voice) > 0) { + printf("#%d (%d)\nid: %s\nvoice: \"%s\"\n", $numid, $i, $id, $voice); + } + } +} Property changes on: genlangxml ___________________________________________________________________ Name: svn:executable + * Index: langv2toxml =================================================================== --- langv2toxml (revision 0) +++ langv2toxml (revision 0) @@ -0,0 +1,130 @@ +#!/usr/bin/perl +# XML::LibXML documentation: http://cpan.uwinnipeg.ca/htdocs/XML-LibXML/ + +use XML::LibXML; +use Switch; +use strict; + +sub trim { + my ($string) = @_; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} + +if ($#ARGV < 0) { + print("Usage: langv2toxml languagename\n"); + exit 1; +} + +my $i = 0; +my $currentNode = "language"; +my $comment = ''; +my $ns = 'http://www.rockbox.org/language'; +my $xmlschema; +my $res; + +# Used to hold various nodes +my %nodes; + +# Initialize our document +my $doc = XML::LibXML::Document->new('1.0', 'UTF-8'); +$nodes{'language'} = $doc->createElement("language"); +$nodes{'language'}->setAttribute('name', $ARGV[0]); + +# Set our namespace +$nodes{'language'}->setNamespace($ns); + +# Add a non-active namespace for the schemaLocation +$nodes{'language'}->setNamespace('http://www.w3.org/2001/XMLSchema-instance', 'xsi', 0); +$nodes{'language'}->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation', 'http://www.rockbox.org/language language.xsd'); +$doc->setDocumentElement($nodes{'language'}); + +while () { + my $line = $_; + $i++; + + # Current line is a comment + if ($line =~ /^#/) { + # Attempt to allow multiline comments by remembering if we're in + # a stream of comments. Not strictly necessary, but there you go + if ($comment eq "") { + $comment = "\n"; + } + # Remove the comment sign + $line =~ s/^#+//; + #if (trim($line) ne "") { + $comment .= $line; + #} + } + # Current line is something that isn't a comment + else { + # End any unclosed comments + if ($comment ne "") { + $nodes{'comment'} = $doc->createComment($comment); + $comment = ''; + if ($currentNode eq "source" + || $currentNode eq "dest" + || $currentNode eq "language") { + $nodes{$currentNode}->appendChild($nodes{'comment'}); + $nodes{'comment'} = undef; + } + } + + # If it's not a comment, we don't care about whitespace, so trim it + $line = trim($line); + + # A start-"tag" is encountered + if ($line =~ /^<([a-z]*)>$/) { + $currentNode = $1; + # Yeah, this could be easier done with a hash.. + $nodes{$1} = $doc->createElementNS($ns, $1); + if (defined($nodes{'comment'})) { + $nodes{$1}->appendChild($nodes{'comment'}); + $nodes{'comment'} = undef; + } + } + # An end-"tag" is encountered + elsif ($line =~ /^<\/([a-z]*)>$/) { + my $parent; + switch($1) { + case 'phrase' { $parent = 'language'; } + case (['dest', 'source', 'voice']) { $parent = 'phrase'; } + else { die sprintf("Unknown tag %s on line %d\n", $1, $i); } + } + $nodes{$parent}->appendChild($nodes{$1}); + } + # An id: value pair is encountered + elsif ($line =~ /^([a-z0-9*,_-]+)\s*:\s*"?(.*?)"?$/) { + switch($currentNode) { + case 'phrase' { + $nodes{$currentNode}->setAttribute($1, $2); + } + case (['dest', 'source', 'voice']) { + my $temp = $doc->createElementNS($ns, 'target'); + $temp->setAttribute('name', $1); + $temp->appendTextNode($2); + $nodes{$currentNode}->appendChild($temp); + } + } + } + elsif ($line ne "") { + printf(STDERR "Line %d confused me: %s\n", $i, $line); + } + } +} + +# Validate the schema (not strictly necessary) +$xmlschema = XML::LibXML::Schema->new( location => 'XMLSchema.xsd' ); +$res = eval { $xmlschema->validate(XML::LibXML->new->parse_file('language.xsd')); }; +# Notify if errors occured (not too helpful error messages unfortunately): +die $@ if $@; + +# Validate the document against our schema +$xmlschema = XML::LibXML::Schema->new( location => 'language.xsd' ); +$res = eval { $xmlschema->validate($doc); }; +# Notify if errors occured (not too helpful error messages unfortunately): +die $@ if $@; + +# Else print our document to stdout +print($doc->toString(1)); Property changes on: langv2toxml ___________________________________________________________________ Name: svn:executable + * Index: language.xsd =================================================================== --- language.xsd (revision 0) +++ language.xsd (revision 0) @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: schemavalidate.pl =================================================================== --- schemavalidate.pl (revision 0) +++ schemavalidate.pl (revision 0) @@ -0,0 +1,11 @@ +#!/usr/bin/perl + +use strict; +use XML::LibXML; + +my $url = $ARGV[0]; +my $schema = $ARGV[1]; + +my $doc = XML::LibXML->new->parse_file($url); +my $xmlschema = XML::LibXML::Schema->new( location => $schema ); +$xmlschema->validate( $doc ); Property changes on: schemavalidate.pl ___________________________________________________________________ Name: svn:executable + * Index: XMLSchema.xsd =================================================================== --- XMLSchema.xsd (revision 0) +++ XMLSchema.xsd (revision 0) @@ -0,0 +1,2534 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]> + + + + Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp + Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp + + + + + + The schema corresponding to this document is normative, + with respect to the syntactic constraints it expresses in the + XML Schema language. The documentation (within <documentation> elements) + below, is not normative, but rather highlights important aspects of + the W3C Recommendation of which this is a part + + + + + The simpleType element and all of its members are defined + towards the end of this schema document + + + + + + Get access to the xml: attribute groups for xml:lang + as declared on 'schema' and 'documentation' below + + + + + + + + This type is extended by almost all schema types + to allow attributes from other namespaces to be + added to user schemas. + + + + + + + + + + + + + This type is extended by all types which allow annotation + other than <schema> itself + + + + + + + + + + + + + + + + This group is for the + elements which occur freely at the top level of schemas. + All of their types are based on the "annotated" type by extension. + + + + + + + + + + + + + This group is for the + elements which can self-redefine (see <redefine> below). + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {extension, restriction} + + + + + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {extension, restriction, list, union} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + for maxOccurs + + + + + + + + + + + + for all particles + + + + + + + for element, group and attributeGroup, + which both define and reference + + + + + + + + 'complexType' uses this + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This branch is short for + <complexContent> + <restriction base="xs:anyType"> + ... + </restriction> + </complexContent> + + + + + + + + + + + + + + + Will be restricted to required or forbidden + + + + + + Not allowed if simpleContent child is chosen. + May be overriden by setting on complexContent child. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overrides any setting on complexType parent. + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + + No typeDefParticle group reference + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {substitution, extension, + restriction} + + + + + + + + + + + + + + + + + + + + + + + + + The element element can be used either + at the top level to define an element-type binding globally, + or within a content model to either reference a globally-defined + element or type or declare an element-type binding locally. + The ref form is not allowed at the top level. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for explicit groups, named top-level groups and + group references + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for the three kinds of group + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice with min/max is here to + avoid a pblm with the Elt:All/Choice/Seq + Particle derivation constraint + + + + + + + + + + restricted max/min + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Only elements allowed inside + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple type for the value of the 'namespace' attr of + 'any' and 'anyAttribute' + + + + Value is + ##any - - any non-conflicting WFXML/attribute at all + + ##other - - any non-conflicting WFXML/attribute from + namespace other than targetNS + + ##local - - any unqualified non-conflicting WFXML/attribute + + one or - - any non-conflicting WFXML/attribute from + more URI the listed namespaces + references + (space separated) + + ##targetNamespace or ##local may appear in the above list, to + refer to the targetNamespace of the enclosing + schema or an absent targetNamespace respectively + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in selectors + A utility type, not for public +use + + + + The following pattern is intended to allow XPath + expressions per the following EBNF: + Selector ::= Path ( '|' Path )* + Path ::= ('.//')? Step ( '/' Step )* + Step ::= '.' | NameTest + NameTest ::= QName | '*' | NCName ':' '*' + child:: is also allowed + + + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in fields + A utility type, not for public +use + + + + The following pattern is intended to allow XPath + expressions per the same EBNF as for selector, + with the following change: + Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) + + + + + + + + + + + + + + + + + + + + + + + + + + + The three kinds of identity constraints, all with + type of or derived from 'keybase'. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + A public identifier, per ISO 8879 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + notations for use within XML Schema schemas + + + + + + + + + Not the real urType, but as close an approximation as we can + get in the XML representation + + + + + + + + + + First the built-in primitive datatypes. These definitions are for + information only, the real built-in definitions are magic. + + + + For each built-in datatype in this schema (both primitive and + derived) can be uniquely addressed via a URI constructed + as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the datatype + + For example, to address the int datatype, the URI is: + + http://www.w3.org/2001/XMLSchema#int + + Additionally, each facet definition element can be uniquely + addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the facet + + For example, to address the maxInclusive facet, the URI is: + + http://www.w3.org/2001/XMLSchema#maxInclusive + + Additionally, each facet usage in a built-in datatype definition + can be uniquely addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the datatype, followed + by a period (".") followed by the name of the facet + + For example, to address the usage of the maxInclusive facet in + the definition of int, the URI is: + + http://www.w3.org/2001/XMLSchema#int.maxInclusive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NOTATION cannot be used directly in a schema; rather a type + must be derived from it by specifying at least one enumeration + facet whose value is the name of a NOTATION declared in the + schema. + + + + + + + + + + Now the derived primitive types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern specifies the content of section 2.12 of XML 1.0e2 + and RFC 3066 (Revised version of RFC 1766). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 7 from the XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 5 from the XML spec + + + + + + + + + + + + + + + pattern matches production 4 from the Namespaces in XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + #all or (possibly empty) subset of {restriction, union, list} + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Can be restricted to required or forbidden + + + + + + + + + + + + + + + + + + Required at the top level + + + + + + + + + + + + + + + + + + + Forbidden when nested + + + + + + + + + + + + + + + + + + + We should use a substitution group for facets, but + that's ruled out because it would allow users to + add their own, which we're not ready for yet. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + base attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + itemType attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + + + memberTypes attribute must be non-empty or there must be + at least one simpleType child + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +