Package pywbem :: Module cimxml_parse
[frames] | no frames]

Source Code for Module pywbem.cimxml_parse

  1  # 
  2  # (C) Copyright 2006,2007 Hewlett-Packard Development Company, L.P. 
  3  # 
  4  # This library is free software; you can redistribute it and/or 
  5  # modify it under the terms of the GNU Lesser General Public 
  6  # License as published by the Free Software Foundation; either 
  7  # version 2.1 of the License, or (at your option) any later version. 
  8  # 
  9  # This program is distributed in the hope that it will be useful, but 
 10  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 12  # Lesser General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU Lesser General Public 
 15  # License along with this program; if not, write to the Free Software 
 16  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 17  # 
 18  # Author: Tim Potter <tpot@hp.com> 
 19  # 
 20   
 21  import string 
 22  from xml.dom import pulldom 
 23   
 24  from pywbem import cim_obj 
 25  from pywbem.cim_obj import CIMInstance, CIMInstanceName, CIMQualifier, \ 
 26                             CIMProperty 
 27   
 28  __all__ = ['ParseError', 'make_parser', 'parse_any'] 
 29   
30 -class ParseError(Exception):
31 """This exception is raised when there is a validation error detected 32 by the parser.""" 33 pass
34 35 # 36 # Helper functions 37 # 38
39 -def _get_required_attribute(node, attr):
40 """Return an attribute by name. Throw an exception if not present.""" 41 42 if not node.hasAttribute(attr): 43 raise ParseError( 44 'Expecting %s attribute in element %s' % (attr, node.tagName)) 45 46 return node.getAttribute(attr)
47
48 -def _get_attribute(node, attr):
49 """Return an attribute by name, or None if not present.""" 50 51 if node.hasAttribute(attr): 52 return node.getAttribute(attr) 53 54 return None
55
56 -def _get_end_event(parser, tagName):
57 """Check that the next event is the end of a particular tag.""" 58 59 (event, node) = parser.next() 60 61 if event != pulldom.END_ELEMENT or node.tagName != tagName: 62 raise ParseError( 63 'Expecting %s end tag, got %s %s' % (tagName, event, node.tagName))
64
65 -def _is_start(event, node, tagName):
66 """Return true if (event, node) is a start event for tagname.""" 67 return event == pulldom.START_ELEMENT and node.tagName == tagName
68
69 -def _is_end(event, node, tagName):
70 """Return true if (event, node) is an end event for tagname.""" 71 return event == pulldom.END_ELEMENT and node.tagName == tagName
72 73 # <!-- ************************************************** --> 74 # <!-- Root element --> 75 # <!-- ************************************************** --> 76 77 # <!ELEMENT CIM (MESSAGE | DECLARATION)> 78 # <!ATTLIST CIM 79 # CIMVERSION CDATA #REQUIRED 80 # DTDVERSION CDATA #REQUIRED 81 # > 82 83 # <!-- ************************************************** --> 84 # <!-- Object declaration elements --> 85 # <!-- ************************************************** --> 86 87 # <!ELEMENT DECLARATION (DECLGROUP | DECLGROUP.WITHNAME | DECLGROUP.WITHPATH)+> 88 # <!ELEMENT DECLGROUP ((LOCALNAMESPACEPATH | NAMESPACEPATH)?, 89 # QUALIFIER.DECLARATION*, VALUE.OBJECT*)> 90 # <!ELEMENT DECLGROUP.WITHNAME ((LOCALNAMESPACEPATH | NAMESPACEPATH)?, 91 # QUALIFIER.DECLARATION*, VALUE.NAMEDOBJECT*)> 92 # <!ELEMENT DECLGROUP.WITHPATH (VALUE.OBJECTWITHPATH | 93 # VALUE.OBJECTWITHLOCALPATH)*> 94 # <!ELEMENT QUALIFIER.DECLARATION (SCOPE?, (VALUE | VALUE.ARRAY)?)> 95 # <!ATTLIST QUALIFIER.DECLARATION 96 # %CIMName; 97 # %CIMType; #REQUIRED 98 # ISARRAY (true|false) #IMPLIED 99 # %ArraySize; 100 # %QualifierFlavor; 101 # > 102 # <!ELEMENT SCOPE EMPTY> 103 # <!ATTLIST SCOPE 104 # CLASS (true | false) "false" 105 # ASSOCIATION (true | false) "false" 106 # REFERENCE (true | false) "false" 107 # PROPERTY (true | false) "false" 108 # METHOD (true | false) "false" 109 # PARAMETER (true | false) "false" 110 # INDICATION (true | false) "false" 111 # > 112 113 # <!-- ************************************************** --> 114 # <!-- Object Value elements --> 115 # <!-- ************************************************** --> 116 117 # <!ELEMENT VALUE (#PCDATA)> 118
119 -def parse_value(parser, event, node):
120 121 value = '' 122 123 (next_event, next_node) = parser.next() 124 125 if next_event == pulldom.CHARACTERS: 126 127 value = next_node.nodeValue 128 129 (next_event, next_node) = parser.next() 130 131 if not _is_end(next_event, next_node, 'VALUE'): 132 raise ParseError('Expecting end VALUE') 133 134 return value
135 136 # <!ELEMENT VALUE.ARRAY (VALUE*)> 137
138 -def parse_value_array(parser, event, node):
139 140 value_array = [] 141 142 (next_event, next_node) = parser.next() 143 144 if _is_start(next_event, next_node, 'VALUE'): 145 146 value_array.append(parse_value(parser, next_event, next_node)) 147 148 while 1: 149 150 (next_event, next_node) = parser.next() 151 152 if _is_end(next_event, next_node, 'VALUE.ARRAY'): 153 break 154 155 if _is_start(next_event, next_node, 'VALUE'): 156 value_array.append(parse_value(parser, next_event, next_node)) 157 else: 158 raise ParseError('Expecting VALUE element') 159 160 return value_array
161 162 # <!ELEMENT VALUE.REFERENCE (CLASSPATH | LOCALCLASSPATH | CLASSNAME | 163 # INSTANCEPATH | LOCALINSTANCEPATH | INSTANCENAME)> 164
165 -def parse_value_reference(parser, event, node):
166 167 (next_event, next_node) = parser.next() 168 169 if _is_start(next_event, next_node, 'CLASSPATH'): 170 result = parse_classpath(parser, next_event, next_node) 171 172 elif _is_start(next_event, next_node, 'LOCALCLASSPATH'): 173 result = parse_localclasspath(parser, next_event, next_node) 174 175 elif _is_start(next_event, next_node, 'CLASSNAME'): 176 result = parse_classname(parser, next_event, next_node) 177 178 elif _is_start(next_event, next_node, 'INSTANCEPATH'): 179 result = parse_instancepath(parser, next_event, next_node) 180 181 elif _is_start(next_event, next_node, 'LOCALINSTANCEPATH'): 182 result = parse_localinstancepath(parser, next_event, next_node) 183 184 elif _is_start(next_event, next_node, 'INSTANCENAME'): 185 result = parse_instancename(parser, next_event, next_node) 186 187 else: 188 raise ParseError('Expecting (CLASSPATH | LOCALCLASSPATH | CLASSNAME ' 189 '| INSTANCEPATH | LOCALINSTANCEPATH | INSTANCENAME)') 190 191 _get_end_event(parser, 'VALUE.REFERENCE') 192 193 return result
194 195 # <!ELEMENT VALUE.REFARRAY (VALUE.REFERENCE*)> 196 # <!ELEMENT VALUE.OBJECT (CLASS | INSTANCE)> 197 # <!ELEMENT VALUE.NAMEDINSTANCE (INSTANCENAME, INSTANCE)> 198 # <!ELEMENT VALUE.NAMEDOBJECT (CLASS | (INSTANCENAME, INSTANCE))> 199 # <!ELEMENT VALUE.OBJECTWITHLOCALPATH ((LOCALCLASSPATH, CLASS) | 200 # (LOCALINSTANCEPATH, INSTANCE))> 201 # <!ELEMENT VALUE.OBJECTWITHPATH ((CLASSPATH, CLASS) | 202 # (INSTANCEPATH, INSTANCE))> 203 # <!ELEMENT VALUE.NULL EMPTY> 204 205 # <!-- ************************************************** --> 206 # <!-- Object naming and locating elements --> 207 # <!-- ************************************************** --> 208 209 # <!ELEMENT NAMESPACEPATH (HOST, LOCALNAMESPACEPATH)> 210
211 -def parse_namespacepath(parser, event, node):
212 213 (next_event, next_node) = parser.next() 214 215 if not _is_start(next_event, next_node, 'HOST'): 216 raise ParseError('Expecting HOST') 217 218 host = parse_host(parser, next_event, next_node) 219 220 (next_event, next_node) = parser.next() 221 222 if not _is_start(next_event, next_node, 'LOCALNAMESPACEPATH'): 223 raise ParseError('Expecting LOCALNAMESPACEPATH') 224 225 namespacepath = parse_localnamespacepath(parser, next_event, next_node) 226 227 (next_event, next_node) = parser.next() 228 229 if not _is_end(next_event, next_node, 'NAMESPACEPATH'): 230 raise ParseError('Expecting end NAMESPACEPATH') 231 232 return (host, namespacepath)
233 234 # <!ELEMENT LOCALNAMESPACEPATH (NAMESPACE+)> 235
236 -def parse_localnamespacepath(parser, event, node):
237 238 (next_event, next_node) = parser.next() 239 240 namespaces = [] 241 242 if not _is_start(next_event, next_node, 'NAMESPACE'): 243 print next_event, next_node 244 raise ParseError('Expecting NAMESPACE') 245 246 namespaces.append(parse_namespace(parser, next_event, next_node)) 247 248 while 1: 249 250 (next_event, next_node) = parser.next() 251 252 if _is_end(next_event, next_node, 'LOCALNAMESPACEPATH'): 253 break 254 255 if _is_start(next_event, next_node, 'NAMESPACE'): 256 namespaces.append(parse_namespace(parser, next_event, next_node)) 257 else: 258 raise ParseError('Expecting NAMESPACE') 259 260 return string.join(namespaces, '/')
261 262 # <!ELEMENT HOST (#PCDATA)> 263
264 -def parse_host(parser, event, node):
265 266 host = '' 267 268 (next_event, next_node) = parser.next() 269 270 if next_event == pulldom.CHARACTERS: 271 272 host = next_node.nodeValue 273 274 (next_event, next_node) = parser.next() 275 276 if not _is_end(next_event, next_node, 'HOST'): 277 raise ParseError('Expecting end HOST') 278 279 return host
280 281 # <!ELEMENT NAMESPACE EMPTY> 282 # <!ATTLIST NAMESPACE 283 # %CIMName; 284 # > 285
286 -def parse_namespace(parser, event, node):
287 288 name = _get_required_attribute(node, 'NAME') 289 290 (next_event, next_node) = parser.next() 291 292 if not _is_end(next_event, next_node, 'NAMESPACE'): 293 raise ParseError('Expecting end NAMESPACE') 294 295 return name
296 297 # <!ELEMENT CLASSPATH (NAMESPACEPATH, CLASSNAME)> 298 299 # <!ELEMENT LOCALCLASSPATH (LOCALNAMESPACEPATH, CLASSNAME)> 300 301 # <!ELEMENT CLASSNAME EMPTY> 302 # <!ATTLIST CLASSNAME 303 # %CIMName; 304 # > 305 306 # <!ELEMENT INSTANCEPATH (NAMESPACEPATH, INSTANCENAME)> 307
308 -def parse_instancepath(parser, event, node):
309 310 (next_event, next_node) = parser.next() 311 312 if not _is_start(next_event, next_node, 'NAMESPACEPATH'): 313 raise ParseError('Expecting NAMESPACEPATH') 314 315 host, namespacepath = parse_namespacepath(parser, next_event, next_node) 316 317 (next_event, next_node) = parser.next() 318 319 if not _is_start(next_event, next_node, 'INSTANCENAME'): 320 print next_event, next_node 321 raise ParseError('Expecting INSTANCENAME') 322 323 instancename = parse_instancename(parser, next_event, next_node) 324 325 instancename.host = host 326 instancename.namespace = namespacepath 327 328 return instancename
329 330 # <!ELEMENT LOCALINSTANCEPATH (LOCALNAMESPACEPATH, INSTANCENAME)> 331
332 -def parse_localinstancepath(parser, event, node):
333 334 (next_event, next_node) = parser.next() 335 336 if not _is_start(next_event, next_node, 'LOCALNAMESPACEPATH'): 337 raise ParseError('Expecting LOCALNAMESPACEPATH') 338 339 namespacepath = parse_localnamespacepath(parser, next_event, next_node) 340 341 (next_event, next_node) = parser.next() 342 343 if not _is_start(next_event, next_node, 'INSTANCENAME'): 344 raise ParseError('Expecting INSTANCENAME') 345 346 instancename = parse_instancename(parser, next_event, next_node) 347 348 instancename.namespace = namespacepath 349 350 return instancename
351 352 # <!ELEMENT INSTANCENAME (KEYBINDING* | KEYVALUE? | VALUE.REFERENCE?)> 353 # <!ATTLIST INSTANCENAME 354 # %ClassName; 355 # > 356
357 -def parse_instancename(parser, event, node):
358 359 classname = _get_required_attribute(node, 'CLASSNAME') 360 keybindings = [] 361 362 (next_event, next_node) = parser.next() 363 364 if _is_start(next_event, next_node, 'KEYBINDING'): 365 366 keybindings.append(parse_keybinding(parser, next_event, next_node)) 367 368 while 1: 369 370 (next_event, next_node) = parser.next() 371 372 if _is_end(next_event, next_node, 'INSTANCENAME'): 373 break 374 375 if _is_start(next_event, next_node, 'KEYBINDING'): 376 keybindings.append( 377 parse_keybinding(parser, next_event, next_node)) 378 else: 379 raise ParseError('Expecting KEYBINDING element') 380 381 if _is_end(next_event, next_node, 'INSTANCENAME'): 382 pass 383 384 elif _is_start(next_event, next_node, 'KEYVALUE'): 385 keybindings.append(('', parse_keyvalue(parser, next_event, next_node))) 386 387 elif _is_start(next_event, next_node, 'VALUE.REFERENCE'): 388 keybindings.append( 389 parse_value_reference(parser, next_event, next_node)) 390 391 else: 392 raise ParseError( 393 'Expecting KEYBINDING* | KEYVALUE? | VALUE.REFERENCE') 394 395 return CIMInstanceName(classname, keybindings)
396 397 # <!ELEMENT OBJECTPATH (INSTANCEPATH | CLASSPATH)> 398 399 # <!ELEMENT KEYBINDING (KEYVALUE | VALUE.REFERENCE)> 400 # <!ATTLIST KEYBINDING 401 # %CIMName; 402 # > 403
404 -def parse_keybinding(parser, event, node):
405 406 name = _get_required_attribute(node, 'NAME') 407 408 (next_event, next_node) = parser.next() 409 410 if _is_start(next_event, next_node, 'KEYVALUE'): 411 keyvalue = parse_keyvalue(parser, next_event, next_node) 412 result = (name, keyvalue) 413 414 elif _is_start(next_event, next_node, 'VALUE.REFERENCE'): 415 value_reference = parse_value_reference(parser, next_event, next_node) 416 result = (name, value_reference) 417 418 else: 419 raise ParseError('Expecting KEYVALUE or VALUE.REFERENCE element') 420 421 _get_end_event(parser, 'KEYBINDING') 422 423 return result
424 425 # <!ELEMENT KEYVALUE (#PCDATA)> 426 # <!ATTLIST KEYVALUE 427 # VALUETYPE (string | boolean | numeric) "string" 428 # %CIMType; #IMPLIED 429 # > 430
431 -def parse_keyvalue(parser, event, node):
432 433 valuetype = _get_required_attribute(node, 'VALUETYPE') 434 type = _get_attribute(node, 'TYPE') 435 436 (next_event, next_node) = parser.next() 437 438 if next_event != pulldom.CHARACTERS: 439 raise ParseError('Expecting character data') 440 441 value = next_node.nodeValue 442 443 if valuetype == 'string': 444 pass 445 446 elif valuetype == 'boolean': 447 448 # CIM-XML says "These values MUST be treated as 449 # case-insensitive" (even though the XML definition 450 # requires them to be lowercase.) 451 452 p = value.strip().lower() 453 454 if p == 'true': 455 value = True 456 elif p == 'false': 457 value = False 458 else: 459 raise ParseError('invalid boolean value "%s"' % `p`) 460 461 elif valuetype == 'numeric': 462 463 try: 464 465 # XXX: Use TYPE attribute to create named CIM type. 466 # if attrs(tt).has_key('TYPE'): 467 # return cim_obj.tocimobj(attrs(tt)['TYPE'], p.strip()) 468 469 # XXX: Would like to use long() here, but that tends to cause 470 # trouble when it's written back out as '2L' 471 472 value = int(value.strip(), 0) 473 474 except ValueError: 475 raise ParseError( 476 'invalid numeric value "%s"' % value) 477 478 else: 479 raise ParseError('Invalid VALUETYPE') 480 481 _get_end_event(parser, 'KEYVALUE') 482 483 return value
484 485 # <!-- ************************************************** --> 486 # <!-- Object definition elements --> 487 # <!-- ************************************************** --> 488 489 # <!ELEMENT CLASS (QUALIFIER*, (PROPERTY | PROPERTY.ARRAY | 490 # PROPERTY.REFERENCE)*, METHOD*)> 491 # <!ATTLIST CLASS 492 # %CIMName; 493 # %SuperClass; 494 # > 495 496 # <!ELEMENT INSTANCE (QUALIFIER*, (PROPERTY | PROPERTY.ARRAY | 497 # PROPERTY.REFERENCE)*)> 498 # <!ATTLIST INSTANCE 499 # %ClassName; 500 # xml:lang NMTOKEN #IMPLIED 501 # > 502
503 -def parse_instance(parser, event, node):
504 505 classname = _get_required_attribute(node, 'CLASSNAME') 506 507 properties = [] 508 qualifiers = [] 509 510 (next_event, next_node) = parser.next() 511 512 if _is_start(next_event, next_node, 'QUALIFIER'): 513 514 qualifiers.append(parse_qualifier(parser, next_event, next_node)) 515 516 while 1: 517 518 (next_event, next_node) = parser.next() 519 520 if _is_start(next_event, next_node, 'PROPERTY') or \ 521 _is_start(next_event, next_node, 'PROPERTY.ARRAY') or \ 522 _is_start(next_event, next_node, 'PROPERTY.REFERENCE') or \ 523 _is_end(next_event, next_node, 'INSTANCE'): 524 break 525 526 if _is_start(next_event, next_node, 'QUALIFIER'): 527 qualifiers.append( 528 parse_qualifier(parser, next_event, next_node)) 529 else: 530 raise ParseError('Expecting QUALIFIER') 531 532 while 1: 533 534 if _is_end(next_event, next_node, 'INSTANCE'): 535 break 536 537 if _is_start(next_event, next_node, 'PROPERTY'): 538 properties.append(parse_property(parser, next_event, next_node)) 539 540 elif _is_start(next_event, next_node, 'PROPERTY.ARRAY'): 541 properties.append( 542 parse_property_array(parser, next_event, next_node)) 543 544 elif _is_start(next_event, next_node, 'PROPERTY.REFERENCE'): 545 properties.append( 546 parse_property_reference(parser, next_event, next_node)) 547 else: 548 raise ParseError( 549 'Expecting (PROPERTY | PROPERTY.ARRAY | PROPERTY.REFERENCE)') 550 551 (next_event, next_node) = parser.next() 552 553 if not _is_end(next_event, next_node, 'INSTANCE'): 554 raise ParseError('Expecting end INSTANCE') 555 556 return CIMInstance( 557 classname, 558 properties=dict([(x.name, x) for x in properties]), 559 qualifiers=dict([(x.name, x) for x in qualifiers]))
560 561 # <!ELEMENT QUALIFIER ((VALUE | VALUE.ARRAY)?)> 562 # <!ATTLIST QUALIFIER 563 # %CIMName; 564 # %CIMType; #REQUIRED 565 # %Propagated; 566 # %QualifierFlavor; 567 # xml:lang NMTOKEN #IMPLIED 568 # > 569
570 -def parse_qualifier(parser, event, node):
571 572 name = _get_required_attribute(node, 'NAME') 573 type = _get_required_attribute(node, 'TYPE') 574 propagated = _get_attribute(node, 'PROPAGATED') 575 576 (next_event, next_node) = parser.next() 577 578 if _is_end(next_event, next_node, 'QUALIFIER'): 579 return CIMQualifier(name, None, type=type) 580 581 if _is_start(next_event, next_node, 'VALUE'): 582 value = parse_value(parser, next_event, next_node) 583 elif _is_start(next_event, next_node, 'VALUE.ARRAY'): 584 value = parse_value_array(parser, next_event, next_node) 585 else: 586 raise ParseError('Expecting (VALUE | VALUE.ARRAY)') 587 588 result = CIMQualifier(name, cim_obj.tocimobj(type, value)) 589 590 _get_end_event(parser, 'QUALIFIER') 591 592 return result
593 594 # <!ELEMENT PROPERTY (QUALIFIER*, VALUE?)> 595 # <!ATTLIST PROPERTY 596 # %CIMName; 597 # %ClassOrigin; 598 # %Propagated; 599 # %CIMType; #REQUIRED 600 # xml:lang NMTOKEN #IMPLIED 601 # > 602
603 -def parse_property(parser, event, node):
604 605 name = _get_required_attribute(node, 'NAME') 606 type = _get_required_attribute(node, 'TYPE') 607 608 class_origin = _get_attribute(node, 'CLASSORIGIN') 609 propagated = _get_attribute(node, 'PROPAGATED') 610 611 qualifiers = [] 612 value = None 613 614 (next_event, next_node) = parser.next() 615 616 if _is_start(next_event, next_node, 'QUALIFIER'): 617 618 qualifiers.append(parse_qualifier(parser, next_event, next_node)) 619 620 while 1: 621 622 (next_event, next_node) = parser.next() 623 624 if _is_start(next_event, next_node, 'VALUE'): 625 break 626 627 if _is_start(next_event, next_node, 'QUALIFIER'): 628 qualifiers.append( 629 parse_qualifier(parser, next_event, next_node)) 630 else: 631 raise ParseError('Expecting QUALIFIER') 632 633 if _is_start(next_event, next_node, 'VALUE'): 634 635 value = parse_value(parser, next_event, next_node) 636 (next_event, next_node) = parser.next() 637 638 if not _is_end(next_event, next_node, 'PROPERTY'): 639 raise ParseError('Expecting end PROPERTY') 640 641 return CIMProperty( 642 name, 643 cim_obj.tocimobj(type, value), 644 type=type, 645 class_origin=class_origin, 646 propagated=propagated, 647 qualifiers=dict([(x.name, x) for x in qualifiers]))
648 649 # <!ELEMENT PROPERTY.ARRAY (QUALIFIER*, VALUE.ARRAY?)> 650 # <!ATTLIST PROPERTY.ARRAY 651 # %CIMName; 652 # %CIMType; #REQUIRED 653 # %ArraySize; 654 # %ClassOrigin; 655 # %Propagated; 656 # xml:lang NMTOKEN #IMPLIED 657 # > 658
659 -def parse_property_array(parser, event, node):
660 661 name = _get_required_attribute(node, 'NAME') 662 type = _get_required_attribute(node, 'TYPE') 663 664 array_size = _get_attribute(node, 'ARRAYSIZE') 665 class_origin = _get_attribute(node, 'CLASSORIGIN') 666 propagated = _get_attribute(node, 'PROPAGATED') 667 668 qualifiers = [] 669 value = None 670 671 (next_event, next_node) = parser.next() 672 673 if _is_start(next_event, next_node, 'QUALIFIER'): 674 675 qualifiers.append(parse_qualifier(parser, next_event, next_node)) 676 677 while 1: 678 679 (next_event, next_node) = parser.next() 680 681 if _is_start(next_event, next_node, 'VALUE.ARRAY'): 682 break 683 684 if _is_start(next_event, next_node, 'QUALIFIER'): 685 qualifiers.append( 686 parse_qualifier(parser, next_event, next_node)) 687 else: 688 raise ParseError('Expecting QUALIFIER') 689 690 if _is_start(next_event, next_node, 'VALUE.ARRAY'): 691 692 value = parse_value_array(parser, next_event, next_node) 693 (next_event, next_node) = parser.next() 694 695 if not _is_end(next_event, next_node, 'PROPERTY.ARRAY'): 696 raise ParseError('Expecting end PROPERTY.ARRAY') 697 698 return CIMProperty( 699 name, 700 cim_obj.tocimobj(type, value), 701 type=type, 702 class_origin=class_origin, 703 propagated=propagated, 704 is_array=True, 705 qualifiers=dict([(x.name, x) for x in qualifiers]))
706 707 # <!ELEMENT PROPERTY.REFERENCE (QUALIFIER*, (VALUE.REFERENCE)?)> 708 # <!ATTLIST PROPERTY.REFERENCE 709 # %CIMName; 710 # %ReferenceClass; 711 # %ClassOrigin; 712 # %Propagated; 713 # > 714
715 -def parse_property_reference(parser, event, node):
716 717 name = _get_required_attribute(node, 'NAME') 718 719 class_origin = _get_attribute(node, 'CLASSORIGIN') 720 propagated = _get_attribute(node, 'PROPAGATED') 721 722 qualifiers = [] 723 value = None 724 725 (next_event, next_node) = parser.next() 726 727 if _is_start(next_event, next_node, 'QUALIFIER'): 728 729 qualifiers.append(parse_qualifier(parser, next_event, next_node)) 730 731 while 1: 732 733 (next_event, next_node) = parser.next() 734 735 if _is_start(next_event, next_node, 'VALUE.REFERENCE'): 736 break 737 738 if _is_start(next_event, next_node, 'QUALIFIER'): 739 qualifiers.append( 740 parse_qualifier(parser, next_event, next_node)) 741 742 else: 743 raise ParseError('Expecting QUALIFIER') 744 745 if _is_start(next_event, next_node, 'VALUE.REFERENCE'): 746 747 value = parse_value_reference(parser, next_event, next_node) 748 (next_event, next_node) = parser.next() 749 750 if not _is_end(next_event, next_node, 'PROPERTY.REFERENCE'): 751 raise ParseError('Expecting end PROPERTY.REFERENCE') 752 753 return CIMProperty( 754 name, 755 value, 756 class_origin=class_origin, 757 propagated=propagated, 758 type='reference', 759 qualifiers=dict([(x.name, x) for x in qualifiers]))
760 761 # <!ELEMENT METHOD (QUALIFIER*, (PARAMETER | PARAMETER.REFERENCE | 762 # PARAMETER.ARRAY | PARAMETER.REFARRAY)*)> 763 # <!ATTLIST METHOD 764 # %CIMName; 765 # %CIMType; #IMPLIED 766 # %ClassOrigin; 767 # %Propagated;> 768 769 # <!ELEMENT PARAMETER (QUALIFIER*)> 770 # <!ATTLIST PARAMETER 771 # %CIMName; 772 # %CIMType; #REQUIRED> 773 774 # <!ELEMENT PARAMETER.REFERENCE (QUALIFIER*)> 775 # <!ATTLIST PARAMETER.REFERENCE 776 # %CIMName; 777 # %ReferenceClass; 778 # > 779 780 # <!ELEMENT PARAMETER.ARRAY (QUALIFIER*)> 781 # <!ATTLIST PARAMETER.ARRAY 782 # %CIMName; 783 # %CIMType; #REQUIRED 784 # %ArraySize;> 785 786 # <!ELEMENT PARAMETER.REFARRAY (QUALIFIER*)> 787 # <!ATTLIST PARAMETER.REFARRAY 788 # %CIMName; 789 # %ReferenceClass; 790 # %ArraySize; 791 # > 792 793 # <!ELEMENT TABLECELL.DECLARATION EMPTY> 794 # <!ATTLIST TABLECELL.DECLARATION 795 # %CIMName; 796 # %CIMType; #REQUIRED 797 # ISARRAY (true|false) "false" 798 # %ArraySize; 799 # CELLPOS CDATA #REQUIRED 800 # SORTPOS CDATA #IMPLIED 801 # SORTDIR (ASC|DESC) #IMPLIED 802 # > 803 804 # <!ELEMENT TABLECELL.REFERENCE EMPTY> 805 # <!ATTLIST TABLECELL.REFERENCE 806 # %CIMName; 807 # %ReferenceClass; 808 # ISARRAY (true|false) "false" 809 # %ArraySize; 810 # CELLPOS CDATA #REQUIRED 811 # SORTPOS CDATA #IMPLIED 812 # SORTDIR (ASC|DESC) #IMPLIED 813 # > 814 815 # <!ELEMENT TABLEROW.DECLARATION (TABLECELL.DECLARATION | TABLECELL.REFERENCE)*> 816 817 # <!ELEMENT TABLE (TABLEROW.DECLARATION,(TABLEROW)*)> 818 819 # <!ELEMENT TABLEROW (VALUE | VALUE.ARRAY | VALUE.REFERENCE | VALUE.REFARRAY | 820 # VALUE.NULL)*> 821 822 # <!-- ************************************************** --> 823 # <!-- Message elements --> 824 # <!-- ************************************************** --> 825 826 # <!ELEMENT MESSAGE (SIMPLEREQ | MULTIREQ | SIMPLERSP | MULTIRSP | 827 # SIMPLEEXPREQ | MULTIEXPREQ | SIMPLEEXPRSP | MULTIEXPRSP)> 828 # <!ATTLIST MESSAGE 829 # ID CDATA #REQUIRED 830 # PROTOCOLVERSION CDATA #REQUIRED 831 # > 832 833 # <!ELEMENT MULTIREQ (SIMPLEREQ, SIMPLEREQ+)> 834 835 # <!ELEMENT MULTIEXPREQ (SIMPLEEXPREQ, SIMPLEEXPREQ+)> 836 837 # <!ELEMENT SIMPLEREQ (IMETHODCALL | METHODCALL)> 838 839 # <!ELEMENT SIMPLEEXPREQ (EXPMETHODCALL)> 840 841 # <!ELEMENT IMETHODCALL (LOCALNAMESPACEPATH, IPARAMVALUE*, 842 # RESPONSEDESTINATION?)> 843 # <!ATTLIST IMETHODCALL 844 # %CIMName; 845 # > 846 847 # <!ELEMENT METHODCALL ((LOCALINSTANCEPATH | LOCALCLASSPATH), PARAMVALUE*, 848 # RESPONSEDESTINATION?)> 849 # <!ATTLIST METHODCALL 850 # %CIMName; 851 # > 852 853 # <!ELEMENT EXPMETHODCALL (EXPPARAMVALUE*)> 854 # <!ATTLIST EXPMETHODCALL 855 # %CIMName; 856 # > 857 858 # <!ELEMENT PARAMVALUE (VALUE | VALUE.REFERENCE | VALUE.ARRAY | 859 # VALUE.REFARRAY)?> 860 # <!ATTLIST PARAMVALUE 861 # %CIMName; 862 # %ParamType; #IMPLIED 863 # > 864 865 # <!ELEMENT IPARAMVALUE (VALUE | VALUE.ARRAY | VALUE.REFERENCE | INSTANCENAME | 866 # CLASSNAME | QUALIFIER.DECLARATION | CLASS | INSTANCE | 867 # VALUE.NAMEDINSTANCE)?> 868 # <!ATTLIST IPARAMVALUE 869 # %CIMName; 870 # > 871 872 # <!ELEMENT EXPPARAMVALUE (INSTANCE? | VALUE? | METHODRESPONSE? | 873 # IMETHODRESPONSE?)> 874 # <!ATTLIST EXPPARAMVALUE 875 # %CIMName; 876 # > 877 878 # <!ELEMENT MULTIRSP (SIMPLERSP, SIMPLERSP+)> 879 880 # <!ELEMENT MULTIEXPRSP (SIMPLEEXPRSP, SIMPLEEXPRSP+)> 881 882 # <!ELEMENT SIMPLERSP (METHODRESPONSE | IMETHODRESPONSE | SIMPLEREQACK)> 883 884 # <!ELEMENT SIMPLEEXPRSP (EXPMETHODRESPONSE)> 885 886 # <!ELEMENT METHODRESPONSE (ERROR | (RETURNVALUE?, PARAMVALUE*))> 887 # <!ATTLIST METHODRESPONSE 888 # %CIMName; 889 # > 890 891 # <!ELEMENT EXPMETHODRESPONSE (ERROR | IRETURNVALUE?)> 892 # <!ATTLIST EXPMETHODRESPONSE 893 # %CIMName; 894 # > 895 896 # <!ELEMENT IMETHODRESPONSE (ERROR | IRETURNVALUE?)> 897 # <!ATTLIST IMETHODRESPONSE 898 # %CIMName; 899 # > 900 901 # <!ELEMENT ERROR (INSTANCE*)> 902 # <!ATTLIST ERROR 903 # CODE CDATA #REQUIRED 904 # DESCRIPTION CDATA #IMPLIED 905 # > 906 907 # <!ELEMENT RETURNVALUE (VALUE | VALUE.REFERENCE)> 908 # <!ATTLIST RETURNVALUE 909 # %ParamType; #IMPLIED 910 # > 911 912 # <!ELEMENT IRETURNVALUE (CLASSNAME* | INSTANCENAME* | VALUE* | 913 # VALUE.OBJECTWITHPATH* | VALUE.OBJECTWITHLOCALPATH* | 914 # VALUE.OBJECT* | OBJECTPATH* | QUALIFIER.DECLARATION* | 915 # VALUE.ARRAY? | VALUE.REFERENCE? | CLASS* | INSTANCE* | 916 # VALUE.NAMEDINSTANCE*)> 917 918 # <!ELEMENT RESPONSEDESTINATION (INSTANCE)> 919 920 # <!ELEMENT SIMPLEREQACK (ERROR?)> 921 # <!ATTLIST SIMPLEREQACK 922 # INSTANCEID CDATA #REQUIRED 923 # > 924
925 -def make_parser(stream_or_string):
926 """Create a xml.dom.pulldom parser.""" 927 928 if type(stream_or_string) == str or type(stream_or_string) == unicode: 929 930 # XXX: the pulldom.parseString() function doesn't seem to 931 # like operating on unicode strings! 932 933 return pulldom.parseString(str(stream_or_string)) 934 935 else: 936 937 return pulldom.parse(stream_or_string)
938
939 -def parse_any(stream_or_string):
940 """Parse any XML string or stream.""" 941 942 parser = make_parser(stream_or_string) 943 944 (event, node) = parser.next() 945 946 if event != pulldom.START_DOCUMENT: 947 raise ParseError('Expecting document start') 948 949 (event, node) = parser.next() 950 951 if event != pulldom.START_ELEMENT: 952 raise ParseError('Expecting element start') 953 954 fn_name = 'parse_%s' % node.tagName.lower().replace('.', '_') 955 fn = globals().get(fn_name) 956 if fn is None: 957 raise ParseError('No parser for element %s' % node.tagName) 958 959 return fn(parser, event, node)
960 961 # Test harness 962 963 if __name__ == '__main__': 964 import sys 965 print parse_any(sys.stdin) 966