1 /* XMLSchemaBuilder.java -- 2 Copyright (C) 2006 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 package gnu.xml.validation.xmlschema; 39 40 import java.util.LinkedHashSet; 41 import java.util.Set; 42 import java.util.StringTokenizer; 43 import javax.xml.XMLConstants; 44 import javax.xml.namespace.QName; 45 import org.relaxng.datatype.DatatypeException; 46 import org.relaxng.datatype.DatatypeLibrary; 47 import org.relaxng.datatype.helpers.DatatypeLibraryLoader; 48 import org.w3c.dom.NamedNodeMap; 49 import org.w3c.dom.Node; 50 import gnu.xml.validation.datatype.Annotation; 51 import gnu.xml.validation.datatype.SimpleType; 52 import gnu.xml.validation.datatype.Type; 53 54 /** 55 * Parses an XML Schema DOM tree, constructing a compiled internal 56 * representation. 57 * 58 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> 59 */ 60 class XMLSchemaBuilder 61 { 62 63 XMLSchema schema; 64 final DatatypeLibrary typeLibrary; 65 XMLSchemaBuilder()66 XMLSchemaBuilder() 67 { 68 final String ns = XMLConstants.W3C_XML_SCHEMA_NS_URI; 69 typeLibrary = new DatatypeLibraryLoader().createDatatypeLibrary(ns); 70 } 71 parseSchema(Node node)72 void parseSchema(Node node) 73 throws DatatypeException 74 { 75 String uri = node.getNamespaceURI(); 76 String name = node.getLocalName(); 77 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 78 node.getNodeType() == Node.ELEMENT_NODE) 79 { 80 if ("schema".equals(name)) 81 { 82 NamedNodeMap attrs = node.getAttributes(); 83 String targetNamespace = getAttribute(attrs, "targetNamespace"); 84 String version = getAttribute(attrs, "version"); 85 String fd = getAttribute(attrs, "finalDefault"); 86 int finalDefault = parseFullDerivationSet(fd); 87 String bd = getAttribute(attrs, "blockDefault"); 88 int blockDefault = parseBlockSet(bd); 89 String afd = getAttribute(attrs, "attributeFormDefault"); 90 boolean attributeFormQualified = "qualified".equals(afd); 91 String efd = getAttribute(attrs, "elementFormDefault"); 92 boolean elementFormQualified = "qualified".equals(efd); 93 schema = new XMLSchema(targetNamespace, version, 94 finalDefault, blockDefault, 95 attributeFormQualified, 96 elementFormQualified); 97 for (Node child = node.getFirstChild(); child != null; 98 child = child.getNextSibling()) 99 { 100 parseTopLevelElement(child); 101 } 102 return; 103 } 104 } 105 // TODO throw schema exception 106 } 107 parseTopLevelElement(Node node)108 void parseTopLevelElement(Node node) 109 throws DatatypeException 110 { 111 String uri = node.getNamespaceURI(); 112 String name = node.getLocalName(); 113 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 114 node.getNodeType() == Node.ELEMENT_NODE) 115 { 116 if ("element".equals(name)) 117 { 118 ElementDeclaration ed = 119 (ElementDeclaration) parseElement(node, null); 120 schema.elementDeclarations.put(ed.name, ed); 121 // TODO 122 } 123 else if ("attribute".equals(name)) 124 { 125 AttributeDeclaration ad = 126 (AttributeDeclaration) parseAttribute(node, true); 127 schema.attributeDeclarations.put(ad.name, ad); 128 // TODO 129 } 130 else if ("type".equals(name)) 131 { 132 // TODO 133 } 134 else if ("group".equals(name)) 135 { 136 // TODO 137 } 138 else if ("attributeGroup".equals(name)) 139 { 140 // TODO 141 } 142 else if ("notation".equals(name)) 143 { 144 // TODO 145 } 146 else if ("identityConstraint".equals(name)) 147 { 148 // TODO 149 } 150 } 151 // TODO throw schema exception 152 } 153 parseAttribute(Node node, boolean scope)154 Object parseAttribute(Node node, boolean scope) 155 throws DatatypeException 156 { 157 NamedNodeMap attrs = node.getAttributes(); 158 String def = getAttribute(attrs, "default"); 159 String fixed = getAttribute(attrs, "fixed"); 160 int constraintType = AttributeDeclaration.NONE; 161 String constraintValue = null; 162 if (def != null) 163 { 164 constraintType = AttributeDeclaration.DEFAULT; 165 constraintValue = def; 166 } 167 else if (fixed != null) 168 { 169 constraintType = AttributeDeclaration.FIXED; 170 constraintValue = fixed; 171 } 172 // TODO form = (qualified | unqualified) 173 String attrName = getAttribute(attrs, "name"); 174 String attrNamespace = getAttribute(attrs, "targetNamespace"); 175 String ref = getAttribute(attrs, "ref"); 176 String use = getAttribute(attrs, "use"); 177 String type = getAttribute(attrs, "type"); 178 SimpleType datatype = (type == null) ? null : 179 parseSimpleType(asQName(type, node)); 180 Annotation annotation = null; 181 for (Node child = node.getFirstChild(); child != null; 182 child = child.getNextSibling()) 183 { 184 String uri = child.getNamespaceURI(); 185 String name = child.getLocalName(); 186 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 187 child.getNodeType() == Node.ELEMENT_NODE) 188 { 189 if ("annotation".equals(name)) 190 { 191 annotation = parseAnnotation(child); 192 } 193 else if ("simpleType".equals(name)) 194 { 195 datatype = parseSimpleType(child); 196 } 197 else 198 { 199 // TODO throw schema exception 200 } 201 } 202 } 203 if (scope) 204 { 205 return new AttributeDeclaration(scope, 206 constraintType, 207 constraintValue, 208 new QName(attrNamespace, attrName), 209 datatype, 210 annotation); 211 } 212 else 213 { 214 boolean required = "required".equals(use); 215 // TODO ref 216 AttributeDeclaration decl = (ref == null) ? 217 new AttributeDeclaration(scope, 218 AttributeDeclaration.NONE, 219 null, 220 new QName(attrNamespace, attrName), 221 datatype, 222 annotation) : 223 /*schema.getAttributeDeclaration(ref)*/ null; 224 return new AttributeUse(required, 225 constraintType, 226 constraintValue, 227 decl); 228 } 229 } 230 parseFullDerivationSet(String value)231 int parseFullDerivationSet(String value) 232 { 233 int ret = XMLSchema.FINAL_NONE; 234 if ("#all".equals(value)) 235 { 236 ret = XMLSchema.FINAL_ALL; 237 } 238 else 239 { 240 StringTokenizer st = new StringTokenizer(value, " "); 241 while (st.hasMoreTokens()) 242 { 243 String token = st.nextToken(); 244 if ("extension".equals(token)) 245 { 246 ret |= XMLSchema.FINAL_EXTENSION; 247 } 248 else if ("restriction".equals(token)) 249 { 250 ret |= XMLSchema.FINAL_RESTRICTION; 251 } 252 else if ("list".equals(token)) 253 { 254 ret |= XMLSchema.FINAL_LIST; 255 } 256 else if ("union".equals(token)) 257 { 258 ret |= XMLSchema.FINAL_UNION; 259 } 260 } 261 } 262 return ret; 263 } 264 parseSimpleTypeDerivationSet(String value)265 int parseSimpleTypeDerivationSet(String value) 266 { 267 int ret = XMLSchema.FINAL_NONE; 268 if ("#all".equals(value)) 269 { 270 ret = XMLSchema.FINAL_LIST | 271 XMLSchema.FINAL_UNION | 272 XMLSchema.FINAL_RESTRICTION; 273 } 274 else 275 { 276 StringTokenizer st = new StringTokenizer(value, " "); 277 while (st.hasMoreTokens()) 278 { 279 String token = st.nextToken(); 280 if ("list".equals(token)) 281 { 282 ret |= XMLSchema.FINAL_LIST; 283 } 284 else if ("union".equals(token)) 285 { 286 ret |= XMLSchema.FINAL_UNION; 287 } 288 else if ("restriction".equals(token)) 289 { 290 ret |= XMLSchema.FINAL_RESTRICTION; 291 } 292 } 293 } 294 return ret; 295 } 296 parseComplexTypeDerivationSet(String value)297 int parseComplexTypeDerivationSet(String value) 298 { 299 int ret = XMLSchema.FINAL_NONE; 300 if ("#all".equals(value)) 301 { 302 ret = XMLSchema.FINAL_EXTENSION | XMLSchema.FINAL_RESTRICTION; 303 } 304 else 305 { 306 StringTokenizer st = new StringTokenizer(value, " "); 307 while (st.hasMoreTokens()) 308 { 309 String token = st.nextToken(); 310 if ("extension".equals(token)) 311 { 312 ret |= XMLSchema.FINAL_EXTENSION; 313 } 314 else if ("restriction".equals(token)) 315 { 316 ret |= XMLSchema.FINAL_RESTRICTION; 317 } 318 } 319 } 320 return ret; 321 } 322 parseBlockSet(String value)323 int parseBlockSet(String value) 324 { 325 int ret = XMLSchema.BLOCK_NONE; 326 if ("#all".equals(value)) 327 { 328 ret = XMLSchema.BLOCK_ALL; 329 } 330 else 331 { 332 StringTokenizer st = new StringTokenizer(value, " "); 333 while (st.hasMoreTokens()) 334 { 335 String token = st.nextToken(); 336 if ("extension".equals(token)) 337 { 338 ret |= XMLSchema.BLOCK_EXTENSION; 339 } 340 else if ("restriction".equals(token)) 341 { 342 ret |= XMLSchema.BLOCK_RESTRICTION; 343 } 344 else if ("substitution".equals(token)) 345 { 346 ret |= XMLSchema.BLOCK_SUBSTITUTION; 347 } 348 } 349 } 350 return ret; 351 } 352 parseComplexTypeBlockSet(String value)353 int parseComplexTypeBlockSet(String value) 354 { 355 int ret = XMLSchema.BLOCK_NONE; 356 if ("#all".equals(value)) 357 { 358 ret = XMLSchema.BLOCK_EXTENSION | XMLSchema.BLOCK_RESTRICTION; 359 } 360 else 361 { 362 StringTokenizer st = new StringTokenizer(value, " "); 363 while (st.hasMoreTokens()) 364 { 365 String token = st.nextToken(); 366 if ("extension".equals(token)) 367 { 368 ret |= XMLSchema.BLOCK_EXTENSION; 369 } 370 else if ("restriction".equals(token)) 371 { 372 ret |= XMLSchema.BLOCK_RESTRICTION; 373 } 374 } 375 } 376 return ret; 377 } 378 parseElement(Node node, ElementDeclaration parent)379 Object parseElement(Node node, ElementDeclaration parent) 380 throws DatatypeException 381 { 382 NamedNodeMap attrs = node.getAttributes(); 383 Integer minOccurs = null; 384 Integer maxOccurs = null; 385 Node parentNode = node.getParentNode(); 386 boolean notTopLevel = !"schema".equals(parentNode.getLocalName()); 387 if (notTopLevel) 388 { 389 String ref = getAttribute(attrs, "ref"); 390 if (ref != null) 391 { 392 minOccurs = getOccurrence(getAttribute(attrs, "minOccurs")); 393 maxOccurs = getOccurrence(getAttribute(attrs, "maxOccurs")); 394 // TODO resolve top-level element declaration 395 ElementDeclaration ad = null; 396 return new Particle(minOccurs, maxOccurs, ad); 397 } 398 } 399 String elementName = getAttribute(attrs, "name"); 400 String elementNamespace = getAttribute(attrs, "targetNamespace"); 401 String type = getAttribute(attrs, "type"); 402 Type datatype = (type != null) ? 403 parseSimpleType(asQName(type, node)) : null; 404 int scope = (parent == null) ? 405 XMLSchema.GLOBAL : 406 XMLSchema.LOCAL; 407 String def = getAttribute(attrs, "default"); 408 String fixed = getAttribute(attrs, "fixed"); 409 int constraintType = AttributeDeclaration.NONE; 410 String constraintValue = null; 411 if (def != null) 412 { 413 constraintType = AttributeDeclaration.DEFAULT; 414 constraintValue = def; 415 } 416 else if (fixed != null) 417 { 418 constraintType = AttributeDeclaration.FIXED; 419 constraintValue = fixed; 420 } 421 String sg = getAttribute(attrs, "substitutionGroup"); 422 QName substitutionGroup = QName.valueOf(sg); 423 String sgPrefix = substitutionGroup.getPrefix(); 424 if (sgPrefix != null && !"".equals(sgPrefix)) 425 { 426 String sgName = substitutionGroup.getLocalPart(); 427 String sgNamespace = node.lookupNamespaceURI(sgPrefix); 428 substitutionGroup = new QName(sgNamespace, sgName); 429 } 430 431 String block = getAttribute(attrs, "block"); 432 int substitutionGroupExclusions = (block == null) ? 433 schema.blockDefault : 434 parseBlockSet(block); 435 String final_ = getAttribute(attrs, "final"); 436 int disallowedSubstitutions = (final_ == null) ? 437 schema.finalDefault : 438 parseFullDerivationSet(final_); 439 440 boolean nillable = "true".equals(getAttribute(attrs, "nillable")); 441 boolean isAbstract = "true".equals(getAttribute(attrs, "abstract")); 442 443 if (notTopLevel) 444 { 445 minOccurs = getOccurrence(getAttribute(attrs, "minOccurs")); 446 maxOccurs = getOccurrence(getAttribute(attrs, "maxOccurs")); 447 String form = getAttribute(attrs, "form"); 448 if (form != null) 449 { 450 if ("qualified".equals(form)) 451 { 452 elementNamespace = schema.targetNamespace; 453 } 454 } 455 else if (schema.elementFormQualified) 456 { 457 elementNamespace = schema.targetNamespace; 458 } 459 } 460 ElementDeclaration ed = 461 new ElementDeclaration(new QName(elementNamespace, elementName), 462 datatype, 463 scope, parent, 464 constraintType, constraintValue, 465 nillable, 466 substitutionGroup, 467 substitutionGroupExclusions, 468 disallowedSubstitutions, 469 isAbstract); 470 471 for (Node child = node.getFirstChild(); child != null; 472 child = child.getNextSibling()) 473 { 474 String uri = child.getNamespaceURI(); 475 String name = child.getLocalName(); 476 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 477 child.getNodeType() == Node.ELEMENT_NODE) 478 { 479 if ("annotation".equals(name)) 480 { 481 ed.annotation = parseAnnotation(child); 482 } 483 else if ("simpleType".equals(name) && datatype == null) 484 { 485 ed.datatype = parseSimpleType(child); 486 } 487 else if ("complexType".equals(name) && datatype == null) 488 { 489 ed.datatype = parseComplexType(child, ed); 490 } 491 else 492 { 493 // throw schema exception 494 } 495 } 496 } 497 498 if (notTopLevel) 499 { 500 return new Particle(minOccurs, maxOccurs, ed); 501 } 502 else 503 { 504 return ed; 505 } 506 } 507 getOccurrence(String value)508 Integer getOccurrence(String value) 509 { 510 if (value == null) 511 { 512 return new Integer(1); 513 } 514 else if ("unbounded".equals(value)) 515 { 516 return null; 517 } 518 else 519 { 520 return new Integer(value); 521 } 522 } 523 parseSimpleType(QName typeName)524 SimpleType parseSimpleType(QName typeName) 525 throws DatatypeException 526 { 527 SimpleType type = (SimpleType) schema.types.get(typeName); 528 if (!XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(typeName.getNamespaceURI())) 529 return null; 530 String localName = typeName.getLocalPart(); 531 return (SimpleType) typeLibrary.createDatatype(localName); 532 } 533 parseSimpleType(Node simpleType)534 SimpleType parseSimpleType(Node simpleType) 535 throws DatatypeException 536 { 537 NamedNodeMap attrs = simpleType.getAttributes(); 538 String typeFinal = getAttribute(attrs, "final"); 539 if (typeFinal == null) 540 { 541 Node schema = simpleType.getParentNode(); 542 while (schema != null && !"schema".equals(schema.getLocalName())) 543 { 544 schema = schema.getParentNode(); 545 } 546 if (schema != null) 547 { 548 NamedNodeMap schemaAttrs = schema.getAttributes(); 549 typeFinal = getAttribute(schemaAttrs, "finalDefault"); 550 } 551 } 552 int typeFinality = parseSimpleTypeDerivationSet(typeFinal); 553 QName typeName = asQName(getAttribute(attrs, "name"), simpleType); 554 int variety = 0; 555 Set facets = new LinkedHashSet(); 556 int fundamentalFacets = 0; // TODO 557 SimpleType baseType = null; // TODO 558 Annotation annotation = null; 559 // TODO use DatatypeBuilder 560 for (Node child = simpleType.getFirstChild(); child != null; 561 child = child.getNextSibling()) 562 { 563 String uri = child.getNamespaceURI(); 564 String name = child.getLocalName(); 565 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 566 child.getNodeType() == Node.ELEMENT_NODE) 567 { 568 if ("annotation".equals(name)) 569 { 570 annotation = parseAnnotation(child); 571 } 572 else if ("restriction".equals(name)) 573 { 574 // TODO 575 } 576 else if ("list".equals(name)) 577 { 578 variety = SimpleType.LIST; 579 // TODO 580 } 581 else if ("union".equals(name)) 582 { 583 variety = SimpleType.UNION; 584 // TODO 585 } 586 } 587 } 588 return new SimpleType(typeName, variety, facets, fundamentalFacets, 589 baseType, annotation); 590 } 591 parseComplexType(Node complexType, ElementDeclaration parent)592 Type parseComplexType(Node complexType, ElementDeclaration parent) 593 throws DatatypeException 594 { 595 NamedNodeMap attrs = complexType.getAttributes(); 596 QName typeName = asQName(getAttribute(attrs, "name"), complexType); 597 boolean isAbstract = "true".equals(getAttribute(attrs, "abstract")); 598 String block = getAttribute(attrs, "block"); 599 int prohibitedSubstitutions = (block == null) ? 600 schema.blockDefault : 601 parseComplexTypeBlockSet(block); 602 String final_ = getAttribute(attrs, "final"); 603 int finality = (final_ == null) ? 604 schema.finalDefault : 605 parseComplexTypeDerivationSet(final_); 606 ComplexType type = new ComplexType(typeName, isAbstract, 607 prohibitedSubstitutions, finality); 608 boolean mixed = "true".equals(getAttribute(attrs, "mixed")); 609 for (Node child = complexType.getFirstChild(); child != null; 610 child = child.getNextSibling()) 611 { 612 String uri = child.getNamespaceURI(); 613 String name = child.getLocalName(); 614 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 615 child.getNodeType() == Node.ELEMENT_NODE) 616 { 617 if ("simpleContent".equals(name)) 618 { 619 parseSimpleContent(child, type); 620 } 621 } 622 } 623 if (mixed) 624 { 625 type.contentType = XMLSchema.CONTENT_MIXED; 626 } 627 return type; 628 } 629 parseSimpleContent(Node simpleContent, ComplexType type)630 void parseSimpleContent(Node simpleContent, ComplexType type) 631 throws DatatypeException 632 { 633 for (Node child = simpleContent.getFirstChild(); child != null; 634 child = child.getNextSibling()) 635 { 636 String uri = child.getNamespaceURI(); 637 String name = child.getLocalName(); 638 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 639 child.getNodeType() == Node.ELEMENT_NODE) 640 { 641 if ("annotation".equals(name)) 642 { 643 type.annotations.add(parseAnnotation(child)); 644 } 645 else if ("restriction".equals(name)) 646 { 647 type.derivationMethod = XMLSchema.FINAL_RESTRICTION; 648 parseRestriction(child, type); 649 } 650 else if ("extension".equals(name)) 651 { 652 type.derivationMethod = XMLSchema.FINAL_EXTENSION; 653 parseExtension(child, type); 654 } 655 } 656 } 657 } 658 parseRestriction(Node restriction, ComplexType type)659 void parseRestriction(Node restriction, ComplexType type) 660 throws DatatypeException 661 { 662 NamedNodeMap attrs = restriction.getAttributes(); 663 String base = getAttribute(attrs, "base"); 664 QName baseType = asQName(base, restriction); 665 SimpleType simpleType = null; 666 for (Node child = restriction.getFirstChild(); child != null; 667 child = child.getNextSibling()) 668 { 669 String uri = child.getNamespaceURI(); 670 String name = child.getLocalName(); 671 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 672 child.getNodeType() == Node.ELEMENT_NODE) 673 { 674 if ("annotation".equals(name)) 675 { 676 type.annotations.add(parseAnnotation(child)); 677 } 678 else if ("simpleType".equals(name)) 679 { 680 type.contentType = XMLSchema.CONTENT_SIMPLE; 681 simpleType = parseSimpleType(child); 682 } 683 else if ("minExclusive".equals(name)) 684 { 685 } 686 else if ("minInclusive".equals(name)) 687 { 688 } 689 else if ("maxExclusive".equals(name)) 690 { 691 } 692 else if ("maxInclusive".equals(name)) 693 { 694 } 695 else if ("totalDigits".equals(name)) 696 { 697 } 698 else if ("fractionDigits".equals(name)) 699 { 700 } 701 else if ("length".equals(name)) 702 { 703 } 704 else if ("minLength".equals(name)) 705 { 706 } 707 else if ("maxLength".equals(name)) 708 { 709 } 710 else if ("enumeration".equals(name)) 711 { 712 } 713 else if ("whiteSpace".equals(name)) 714 { 715 } 716 else if ("pattern".equals(name)) 717 { 718 } 719 else if ("attribute".equals(name)) 720 { 721 AttributeUse use = 722 (AttributeUse) parseAttribute(child, false); 723 schema.attributeDeclarations.put(use.declaration.name, 724 use.declaration); 725 type.attributeUses.add(use); 726 } 727 else if ("attributeGroup".equals(name)) 728 { 729 NamedNodeMap agAttrs = child.getAttributes(); 730 String ref = getAttribute(agAttrs, "ref"); 731 QName ag = asQName(ref, child); 732 type.attributeUses.add(ag); 733 } 734 else if ("anyAttribute".equals(name)) 735 { 736 type.attributeWildcard = parseAnyAttribute(child); 737 } 738 } 739 } 740 } 741 parseExtension(Node extension, ComplexType type)742 void parseExtension(Node extension, ComplexType type) 743 throws DatatypeException 744 { 745 NamedNodeMap attrs = extension.getAttributes(); 746 String base = getAttribute(attrs, "base"); 747 QName baseType = asQName(base, extension); 748 for (Node child = extension.getFirstChild(); child != null; 749 child = child.getNextSibling()) 750 { 751 String uri = child.getNamespaceURI(); 752 String name = child.getLocalName(); 753 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 754 child.getNodeType() == Node.ELEMENT_NODE) 755 { 756 if ("annotation".equals(name)) 757 { 758 type.annotations.add(parseAnnotation(child)); 759 } 760 else if ("attribute".equals(name)) 761 { 762 AttributeUse use = 763 (AttributeUse) parseAttribute(child, false); 764 schema.attributeDeclarations.put(use.declaration.name, 765 use.declaration); 766 type.attributeUses.add(use); 767 } 768 else if ("attributeGroup".equals(name)) 769 { 770 NamedNodeMap agAttrs = child.getAttributes(); 771 String ref = getAttribute(agAttrs, "ref"); 772 QName ag = asQName(ref, child); 773 type.attributeUses.add(ag); 774 } 775 else if ("anyAttribute".equals(name)) 776 { 777 type.attributeWildcard = parseAnyAttribute(child); 778 } 779 } 780 } 781 } 782 parseAnyAttribute(Node node)783 AnyAttribute parseAnyAttribute(Node node) 784 { 785 NamedNodeMap attrs = node.getAttributes(); 786 String namespace = getAttribute(attrs, "namespace"); 787 String pc = getAttribute(attrs, "processContents"); 788 int processContents = AnyAttribute.STRICT; 789 if ("lax".equals(pc)) 790 { 791 processContents = AnyAttribute.LAX; 792 } 793 else if ("skip".equals(pc)) 794 { 795 processContents = AnyAttribute.SKIP; 796 } 797 AnyAttribute ret = new AnyAttribute(namespace, processContents); 798 for (Node child = node.getFirstChild(); child != null; 799 child = child.getNextSibling()) 800 { 801 String uri = child.getNamespaceURI(); 802 String name = child.getLocalName(); 803 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) && 804 child.getNodeType() == Node.ELEMENT_NODE) 805 { 806 if ("annotation".equals(name)) 807 { 808 ret.annotation = parseAnnotation(child); 809 } 810 } 811 } 812 return ret; 813 } 814 parseAnnotation(Node node)815 Annotation parseAnnotation(Node node) 816 { 817 // TODO 818 return null; 819 } 820 getAttribute(NamedNodeMap attrs, String name)821 private static String getAttribute(NamedNodeMap attrs, String name) 822 { 823 Node attr = attrs.getNamedItem(name); 824 return (attr == null) ? null : attr.getNodeValue(); 825 } 826 asQName(String text, Node resolver)827 private static QName asQName(String text, Node resolver) 828 { 829 QName name = QName.valueOf(text); 830 String prefix = name.getPrefix(); 831 if (prefix != null && prefix.length() > 0) 832 { 833 String uri = resolver.lookupNamespaceURI(prefix); 834 name = new QName(uri, name.getLocalPart()); 835 } 836 return name; 837 } 838 839 } 840