SystemOrganization addCategory: #'PetitXml-Core'! SystemOrganization addCategory: #'PetitXml-Support'! SystemOrganization addCategory: #'PetitXml-Tests'! TestResource subclass: #PPXmlResource instanceVariableNames: 'parsers' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Tests'! !PPXmlResource methodsFor: 'accessing' stamp: 'lr 2/4/2010 14:12'! allXmlDefinitions ^ (Pragma allNamed: #xml: in: self class) collect: [ :each | self perform: each selector ]! ! !PPXmlResource methodsFor: 'accessing' stamp: 'lr 2/4/2010 14:10'! allXsdDefinitions ^ (Pragma allNamed: #xsd in: self class) collect: [ :each | self perform: each selector ]! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! elementFormXsd ^ ' --> '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! elementReferencesXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! externalAttributesXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! forwardRefXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! getBalanceXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! groupXsd ^ ' A price is any one of the following: * Full Price (with amount) * Sale Price (with amount and authorization) * Clearance Price (with amount and authorization) * Free (with authorization) '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! importAuxXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! importBaseXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! includeWithNamespaceXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! includeWithoutNamespaceXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! listXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! mixedContentXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! notationXsd ^ ' Location of the corporate mascot. '! ! !PPXmlResource methodsFor: 'accessing' stamp: 'lr 1/26/2010 13:21'! parserAt: aClass ^ parsers at: aClass name ifAbsentPut: [ aClass new ]! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! restrictionXsd ^ ' '! ! !PPXmlResource methodsFor: 'running' stamp: 'lr 1/7/2010 13:39'! setUp super setUp. parsers := Dictionary new! ! !PPXmlResource methodsFor: 'accessing-xml' stamp: 'lr 2/4/2010 14:09'! shiporderXml ^ ' Alice Smith 123 Maple Street Mill Valley CA 90952 Robert Smith 8 Oak Avenue Old Town PA 95819 Hurry, my lawn is going wild!! Lawnmower 1 148.95 Confirm this is electric Baby Monitor 1 39.98 1999-05-21 '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:11'! shiporderXsd ^ ' Purchase order schema for Example.com. Copyright 2000 Example.com. All rights reserved. '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:12'! simpleContentExtensionXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:12'! subgroupXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:12'! unionXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:12'! unqualifiedTypesXsd ^ ' '! ! !PPXmlResource methodsFor: 'accessing-xsd' stamp: 'lr 2/4/2010 14:12'! xsdXsd ^ ' ]> The schema corresponding to this document is normative, with respect to the syntactic constraints it expresses in the XML Schema Definition 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. See below (at the bottom of this document) for information about the revision and namespace-versioning policy governing this schema document. The simpleType element and all of its members are defined in datatypes.xsd 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 prohibited Not allowed if simpleContent child is chosen. May be overridden 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. This type is used for ''alternative'' elements. 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 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 utility type, not for public use A utility type, not for public use A utility type, not for public use A utility type, not for public use A subset of XPath expressions for use in selectors A utility type, not for public use A subset of XPath expressions for use in fields A utility type, not for public use 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 schema documents Not the real urType, but as close an approximation as we can get in the XML representation In keeping with the XML Schema WG''s standard versioning policy, this schema document will persist at the URI http://www.w3.org/2009/12/XMLSchema.xsd. At the date of issue it can also be found at the URI http://www.w3.org/2009/XMLSchema/XMLSchema.xsd. The schema document at that URI may however change in the future, in order to remain compatible with the latest version of XSD and its namespace. In other words, if XSD or the XML Schema namespace change, the version of this document at http://www.w3.org/2009/XMLSchema/XMLSchema.xsd will change accordingly; the version at http://www.w3.org/2009/12/XMLSchema.xsd will not change. Previous dated (and unchanging) versions of this schema document include: http://www.w3.org/2009/04/XMLSchema.xsd (XSD 1.1 Candidate Recommendation) http://www.w3.org/2004/10/XMLSchema.xsd (XSD 1.0 Recommendation, Second Edition) http://www.w3.org/2001/05/XMLSchema.xsd (XSD 1.0 Recommendation, First Edition) '! ! Object subclass: #PPXmlNode instanceVariableNames: 'parent' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlNode commentStamp: 'lr 2/4/2010 13:27' prior: 0! An abstract XML node.! PPXmlNode subclass: #PPXmlAttributes instanceVariableNames: 'size keys values' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlAttributes commentStamp: 'lr 2/4/2010 13:27' prior: 0! Attributes of an XML node.! !PPXmlAttributes class methodsFor: 'instance creation' stamp: 'lr 2/1/2010 10:50'! new ^ self new: 3! ! !PPXmlAttributes class methodsFor: 'instance creation' stamp: 'lr 2/1/2010 10:50'! new: anInteger ^ self basicNew initialize: anInteger; yourself! ! !PPXmlAttributes methodsFor: 'comparing' stamp: 'lr 2/1/2010 11:11'! = anXmlNode self == anXmlNode ifTrue: [ ^ true ]. self class = anXmlNode class ifFalse: [ ^ false ]. self size = anXmlNode size ifFalse: [ ^ false ]. self keys with: anXmlNode keys do: [ :first :second | first = second ifFalse: [ ^ false ] ]. self values with: anXmlNode values do: [ :first :second | first = second ifFalse: [ ^ false ] ]. ^ true! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 2/1/2010 10:49'! add: anAssociation self at: anAssociation key put: anAssociation value. ^anAssociation! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 2/1/2010 10:49'! associations "Answer a Collection containing the receiver's associations." | result | result := WriteStream on: (Array new: self size). self associationsDo: [ :assoc | result nextPut: assoc ]. ^ result contents! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 10/28/2007 14:42'! at: aKey "Answer the value associated with aKey. Raise an exception, if no such key is defined." ^ self at: aKey ifAbsent: [ self errorKeyNotFound ]! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 10/28/2007 14:42'! at: aKey ifAbsent: aBlock "Answer the value associated with aKey. Evaluate aBlock, if no such key is defined." | index | index := self findIndexFor: aKey. ^ index = 0 ifFalse: [ values at: index ] ifTrue: [ aBlock value ]! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 10/28/2007 14:42'! at: aKey ifAbsentPut: aBlock "Answer the value associated with aKey. Evaluate aBlock, if no such key is defined and store the return value." | index | index := self findIndexFor: aKey. ^ index = 0 ifFalse: [ values at: index ] ifTrue: [ self privateAt: aKey put: aBlock value ]! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 10/28/2007 14:42'! at: aKey ifPresent: aBlock "Lookup aKey in the receiver. If it is present, answer the value of evaluating the given block with the value associated with the key. Otherwise, answer nil." | index | index := self findIndexFor: aKey. ^ index = 0 ifFalse: [ aBlock value: (values at: index) ]! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 10/28/2007 14:42'! at: aKey put: aValue "Set the value of aKey to be aValue." | index | index := self findIndexFor: aKey. ^ index = 0 ifFalse: [ values at: index put: aValue ] ifTrue: [ self privateAt: aKey put: aValue ]! ! !PPXmlAttributes methodsFor: 'enumerating' stamp: 'jf 12/29/2009 20:38'! do: aBlock 1 to: size do: [ :index | aBlock value: (values at: index) ]! ! !PPXmlAttributes methodsFor: 'private' stamp: 'lr 7/12/2007 13:18'! errorKeyNotFound self error: 'Key not found'! ! !PPXmlAttributes methodsFor: 'private' stamp: 'lr 10/28/2007 14:42'! findIndexFor: aKey 1 to: size do: [ :index | (keys at: index) = aKey ifTrue: [ ^ index ] ]. ^ 0! ! !PPXmlAttributes methodsFor: 'private' stamp: 'lr 6/6/2007 19:12'! grow | newKeys newValues | newKeys := Array new: 2 * size. newValues := Array new: 2 * size. 1 to: size do: [ :index | newKeys at: index put: (keys at: index). newValues at: index put: (values at: index) ]. keys := newKeys. values := newValues! ! !PPXmlAttributes methodsFor: 'testing' stamp: 'lr 10/28/2007 14:42'! includesKey: aKey "Answer whether the receiver has a key equal to aKey." ^ (self findIndexFor: aKey) ~= 0! ! !PPXmlAttributes methodsFor: 'initialization' stamp: 'jf 3/13/2009 17:48'! initialize: anInteger self initialize. size := 0. keys := Array new: anInteger. values := Array new: anInteger! ! !PPXmlAttributes methodsFor: 'testing' stamp: 'lr 7/9/2007 08:13'! isEmpty ^ size = 0! ! !PPXmlAttributes methodsFor: 'enumerating' stamp: 'lr 7/9/2007 10:37'! keys ^ keys copyFrom: 1 to: size! ! !PPXmlAttributes methodsFor: 'enumerating' stamp: 'lr 6/7/2007 08:04'! keysAndValuesDo: aBlock 1 to: size do: [ :index | aBlock value: (keys at: index) value: (values at: index) ]! ! !PPXmlAttributes methodsFor: 'enumerating' stamp: 'lr 8/17/2007 11:52'! keysDo: aBlock 1 to: size do: [ :each | aBlock value: (keys at: each) ]! ! !PPXmlAttributes methodsFor: 'copying' stamp: 'lr 7/9/2007 07:50'! postCopy super postCopy. keys := keys copy. values := values copy! ! !PPXmlAttributes methodsFor: 'printing' stamp: 'lr 2/1/2010 10:46'! printXmlOn: aStream self keysAndValuesDo: [ :key :value | aStream nextPut: $ ; nextPutAll: key; nextPut: $=; nextPut: $"; nextPutAll: value; nextPut: $" ]! ! !PPXmlAttributes methodsFor: 'private' stamp: 'lr 6/6/2007 19:28'! privateAt: aKey put: aValue size = keys size ifTrue: [ self grow ]. keys at: (size := size + 1) put: aKey. ^ values at: size put: aValue! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 7/12/2007 13:18'! removeKey: aKey "Remove aKey from the receiver, raise an exception if the element is missing." ^ self removeKey: aKey ifAbsent: [ self errorKeyNotFound ]! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 10/28/2007 14:42'! removeKey: aKey ifAbsent: aBlock "Remove aKey from the receiver, evaluate aBlock if the element is missing." | index value | index := self findIndexFor: aKey. index = 0 ifTrue: [ ^ aBlock value ]. value := values at: index. index to: size - 1 do: [ :i | keys at: i put: (keys at: i + 1). values at: i put: (values at: i + 1) ]. keys at: size put: nil. values at: size put: nil. size := size - 1. ^ value! ! !PPXmlAttributes methodsFor: 'accessing' stamp: 'lr 7/9/2007 10:38'! size ^ size! ! !PPXmlAttributes methodsFor: 'enumerating' stamp: 'lr 7/9/2007 10:38'! values ^ values copyFrom: 1 to: size! ! PPXmlNode subclass: #PPXmlData instanceVariableNames: 'data' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlData commentStamp: 'lr 2/4/2010 13:27' prior: 0! An abstract XML data node.! PPXmlData subclass: #PPXmlComment instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlComment commentStamp: 'lr 2/4/2010 13:27' prior: 0! An XML comment node.! !PPXmlComment methodsFor: 'printing' stamp: 'lr 1/29/2010 14:02'! printXmlOn: aStream aStream nextPutAll: ''! ! !PPXmlData class methodsFor: 'instance creation' stamp: 'lr 1/29/2010 14:01'! data: aString ^ self new data: aString! ! !PPXmlData methodsFor: 'comparing' stamp: 'lr 2/1/2010 11:11'! = anXmlNode self == anXmlNode ifTrue: [ ^ true ]. self class = anXmlNode class ifFalse: [ ^ false ]. ^ self data = anXmlNode data! ! !PPXmlData methodsFor: 'accessing' stamp: 'lr 1/29/2010 14:01'! data ^ data! ! !PPXmlData methodsFor: 'accessing' stamp: 'lr 1/29/2010 14:01'! data: aString data := aString! ! PPXmlData subclass: #PPXmlProcessing instanceVariableNames: 'target' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlProcessing commentStamp: 'lr 2/4/2010 13:27' prior: 0! An XML processing instruction.! !PPXmlProcessing class methodsFor: 'instance creation' stamp: 'lr 1/29/2010 14:01'! target: aTargetString data: aString ^ self new target: aTargetString; data: aString; yourself! ! !PPXmlProcessing methodsFor: 'comparing' stamp: 'lr 2/1/2010 11:12'! = anXmlNode ^ super = anXmlNode and: [ self target = anXmlNode target ]! ! !PPXmlProcessing methodsFor: 'printing' stamp: 'lr 1/29/2010 14:00'! printXmlOn: aStream aStream nextPutAll: ''! ! !PPXmlProcessing methodsFor: 'accessing' stamp: 'lr 1/29/2010 14:00'! target ^ target! ! !PPXmlProcessing methodsFor: 'accessing' stamp: 'lr 1/29/2010 14:00'! target: aString target := aString! ! PPXmlData subclass: #PPXmlText instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlText commentStamp: 'lr 2/4/2010 13:27' prior: 0! An XML text node.! !PPXmlText methodsFor: 'printing' stamp: 'lr 1/29/2010 13:58'! printXmlOn: aStream aStream nextPutAll: data! ! PPXmlNode subclass: #PPXmlDocument instanceVariableNames: 'xmlDeclaration documentType rootElement' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlDocument commentStamp: 'lr 2/4/2010 13:27' prior: 0! An XML root node.! !PPXmlDocument methodsFor: 'comparing' stamp: 'lr 2/1/2010 11:12'! = anXmlNode self == anXmlNode ifTrue: [ ^ true ]. self class = anXmlNode class ifFalse: [ ^ false ]. ^ self xmlDeclaration = anXmlNode xmlDeclaration and: [ self documentType = anXmlNode documentType and: [ self rootElement = anXmlNode rootElement ] ]! ! !PPXmlDocument methodsFor: 'accessing' stamp: 'lr 2/4/2010 13:45'! childNodes ^ Array with: self rootElement! ! !PPXmlDocument methodsFor: 'accessing' stamp: 'lr 2/1/2010 11:00'! documentType ^ documentType! ! !PPXmlDocument methodsFor: 'testing' stamp: 'lr 2/4/2010 13:44'! isDocument ^ true! ! !PPXmlDocument methodsFor: 'copying' stamp: 'lr 2/4/2010 13:55'! postCopy super postCopy. self setXmlDeclaration: self xmlDeclaration copy. self setRootElement: self rootElement copy! ! !PPXmlDocument methodsFor: 'printing' stamp: 'lr 2/1/2010 11:03'! printXmlOn: aStream xmlDeclaration printXmlOn: aStream. documentType isNil ifFalse: [ aStream cr; nextPutAll: documentType ]. aStream cr. rootElement printXmlOn: aStream! ! !PPXmlDocument methodsFor: 'accessing' stamp: 'lr 2/1/2010 11:01'! rootElement ^ rootElement! ! !PPXmlDocument methodsFor: 'initialization' stamp: 'lr 2/4/2010 13:31'! setDocumentType: aString documentType := aString! ! !PPXmlDocument methodsFor: 'initialization' stamp: 'lr 2/4/2010 13:31'! setRootElement: anElement rootElement := anElement setParent: self! ! !PPXmlDocument methodsFor: 'initialization' stamp: 'lr 2/4/2010 13:31'! setXmlDeclaration: aProcessing xmlDeclaration := aProcessing! ! !PPXmlDocument methodsFor: 'accessing' stamp: 'lr 2/1/2010 11:01'! xmlDeclaration ^ xmlDeclaration! ! PPXmlNode subclass: #PPXmlElement instanceVariableNames: 'tag attributes contents' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlElement commentStamp: 'lr 2/4/2010 13:27' prior: 0! An XML element node.! !PPXmlElement class methodsFor: 'instance creation' stamp: 'lr 1/29/2010 14:24'! tag: aString attributes: aDictionary ^ self basicNew initializeTag: aString attributes: aDictionary; yourself! ! !PPXmlElement methodsFor: 'comparing' stamp: 'lr 2/1/2010 11:36'! = anXmlNode self == anXmlNode ifTrue: [ ^ true ]. self class = anXmlNode class ifFalse: [ ^ false ]. (self tag = anXmlNode tag and: [ self attributes = anXmlNode attributes ]) ifFalse: [ ^ false ]. (self contents isNil and: [ anXmlNode contents isNil ]) ifTrue: [ ^ true ]. (self contents isNil or: [ anXmlNode contents isNil ]) ifTrue: [ ^ false ]. (self contents size = anXmlNode contents size) ifFalse: [ ^ false ]. self contents with: anXmlNode contents do: [ :first :second | first = second ifFalse: [ ^ false ] ]. ^ true! ! !PPXmlElement methodsFor: 'accessing' stamp: 'lr 1/26/2010 16:39'! attributes ^ attributes! ! !PPXmlElement methodsFor: 'accessing' stamp: 'lr 2/4/2010 13:46'! childNodes ^ contents ifNil: [ #() ]! ! !PPXmlElement methodsFor: 'accessing' stamp: 'lr 1/29/2010 13:51'! contents ^ contents! ! !PPXmlElement methodsFor: 'initialization' stamp: 'lr 2/4/2010 15:11'! initializeTag: aString attributes: aXmlAttributes self setTag: aString; setAttributes: aXmlAttributes! ! !PPXmlElement methodsFor: 'copying' stamp: 'lr 2/4/2010 13:57'! postCopy super postCopy. self setAttributes: self attributes copy. self contents notNil ifTrue: [ self setContents: self contents copy ]! ! !PPXmlElement methodsFor: 'printing' stamp: 'lr 2/1/2010 10:48'! printXmlOn: aStream aStream nextPut: $<; nextPutAll: tag. attributes printXmlOn: aStream. contents isNil ifTrue: [ aStream nextPutAll: '/>' ] ifFalse: [ aStream nextPut: $>. contents do: [ :each | each printXmlOn: aStream ]. aStream nextPutAll: ' ]! ! !PPXmlElement methodsFor: 'initialization' stamp: 'lr 2/4/2010 13:56'! setAttributes: anXmlAttributes attributes := anXmlAttributes setParent: self! ! !PPXmlElement methodsFor: 'initialization' stamp: 'lr 2/4/2010 13:30'! setContents: anArray anArray do: [ :each | each setParent: self ]. contents := anArray! ! !PPXmlElement methodsFor: 'initialization' stamp: 'lr 2/4/2010 13:56'! setTag: aString tag := aString! ! !PPXmlElement methodsFor: 'accessing' stamp: 'lr 1/29/2010 13:52'! tag ^ tag! ! !PPXmlNode methodsFor: 'accessing-dom' stamp: 'lr 2/4/2010 13:25'! childNodes "Answer a collection of child nodes." ^ #()! ! !PPXmlNode methodsFor: 'accessing-dom' stamp: 'lr 2/4/2010 13:25'! firstChild "Answer the first child of the receiver or nil." ^ self childNodes isEmpty ifFalse: [ self childNodes first ]! ! !PPXmlNode methodsFor: 'testing' stamp: 'lr 2/4/2010 13:44'! isDocument ^ false! ! !PPXmlNode methodsFor: 'accessing-dom' stamp: 'lr 2/4/2010 13:25'! lastChild "Answer the last child of the receiver or nil." ^ self childNodes isEmpty ifFalse: [ self childNodes last ]! ! !PPXmlNode methodsFor: 'accessing-dom' stamp: 'lr 2/4/2010 13:47'! nextSibling "Answer the next sibling of the receiver or nil." | index parent | self parentNode isNil ifTrue: [ ^ nil ]. parent := self parentNode childNodes. index := parent identityIndexOf: self ifAbsent: [ ^ nil ]. ^ parent at: index + 1 ifAbsent: [ ^ nil ]! ! !PPXmlNode methodsFor: 'enumerating' stamp: 'lr 2/4/2010 13:45'! nodesDo: aBlock aBlock value: self. self childNodes do: [ :each | each nodesDo: aBlock ]! ! !PPXmlNode methodsFor: 'accessing' stamp: 'lr 1/29/2010 14:22'! parent "Answer the parent node of the receiver." ^ parent! ! !PPXmlNode methodsFor: 'accessing-dom' stamp: 'lr 2/4/2010 13:26'! parentNode "Answer the parent node of the receiver or nil." ^ parent! ! !PPXmlNode methodsFor: 'copying' stamp: 'lr 2/4/2010 13:54'! postCopy super postCopy. self setParent: nil! ! !PPXmlNode methodsFor: 'accessing-dom' stamp: 'lr 2/4/2010 13:47'! previousSibling "Answer the previous sibling of the receiver or nil." | index parent | self parentNode isNil ifTrue: [ ^ nil ]. parent := self parentNode childNodes. index := parent identityIndexOf: self ifAbsent: [ ^ nil ]. ^ parent at: index - 1 ifAbsent: [ ^ nil ]! ! !PPXmlNode methodsFor: 'printing' stamp: 'lr 1/26/2010 16:45'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' '. self printXmlOn: aStream! ! !PPXmlNode methodsFor: 'printing' stamp: 'lr 1/26/2010 16:45'! printXmlOn: aStream self subclassResponsibility! ! !PPXmlNode methodsFor: 'initialization' stamp: 'lr 1/29/2010 14:22'! setParent: aNode parent := aNode! ! PPFlattenParser subclass: #PPXmlTokenParser instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Support'! !PPXmlTokenParser methodsFor: 'hooks' stamp: 'lr 1/26/2010 11:44'! create: aCollection start: aStartInteger stop: aStopInteger ^ PPToken on: aCollection start: aStartInteger stop: aStopInteger! ! PPCompositeParser subclass: #PPXmlGrammar instanceVariableNames: 'comment whitespace processing nameStartChar nameChar nameToken nmToken misc document element attributes content characterData attribute doctype attributeValue' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlGrammar methodsFor: 'grammar' stamp: 'lr 1/26/2010 14:18'! attribute "[41] Attribute ::= Name Eq AttValue" ^ self parserForAttribute: nameToken value: attributeValue! ! !PPXmlGrammar methodsFor: 'grammar' stamp: 'lr 1/26/2010 14:18'! attributeValue ^ $" asParser negate star flatten! ! !PPXmlGrammar methodsFor: 'grammar' stamp: 'lr 2/1/2010 10:50'! attributes "[40] STag ::= '<' Name (S Attribute)* S? '>' " ^ ((whitespace , attribute) ==> #second) star ==> [ :nodes | nodes inject: PPXmlAttributes new into: [ :dict :each | dict add: each; yourself ] ]! ! !PPXmlGrammar methodsFor: 'grammar-character' stamp: 'lr 1/29/2010 14:19'! characterData "[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)" ^ $< asParser negate plus flatten ==> [ :nodes | PPXmlText data: nodes ]! ! !PPXmlGrammar methodsFor: 'grammar-misc' stamp: 'lr 2/7/2010 20:22'! comment "[15] Comment ::= ''" ^ '' asParser negate star flatten , '-->' asParser ==> [ :nodes | PPXmlComment data: nodes second ]! ! !PPXmlGrammar methodsFor: 'grammar' stamp: 'lr 2/4/2010 16:06'! content "[43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*" ^ self parserForElement: element! ! !PPXmlGrammar methodsFor: 'grammar-misc' stamp: 'lr 2/7/2010 20:23'! doctype "[28] doctypedecl ::= ''" ^ ' asParser! ! !PPXmlGrammar methodsFor: 'grammar' stamp: 'lr 2/1/2010 11:06'! document "[1] document ::= prolog element Misc*" "[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?" ^ self parserForDocument: self parserForRootElement! ! !PPXmlGrammar methodsFor: 'grammar' stamp: 'lr 1/26/2010 13:30'! element "[39] element ::= EmptyElemTag | STag content ETag" ^ (self parserForTag: nameToken attributes: attributes) / (self parserForTag: nameToken attributes: attributes content: content)! ! !PPXmlGrammar methodsFor: 'grammar-character' stamp: 'lr 1/26/2010 09:08'! misc "[27] Misc ::= Comment | PI | S" ^ (whitespace / comment / processing) star! ! !PPXmlGrammar methodsFor: 'token-characters' stamp: 'lr 1/26/2010 09:13'! nameChar "[4a] NameChar ::= NameStartChar | ""-"" | ""."" | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]" ^ PPPredicateParser on: [ :char | char = $- or: [ char = $. or: [ char = $: or: [ char = $_ or: [ char isAlphaNumeric ] ] ] ] ] message: 'name expected'! ! !PPXmlGrammar methodsFor: 'token-characters' stamp: 'lr 1/26/2010 09:13'! nameStartChar "[4] NameStartChar ::= "":"" | [A-Z] | ""_"" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]" ^ PPPredicateParser on: [ :char | char = $: or: [ char = $_ or: [ char isLetter ] ] ] message: 'name expected'! ! !PPXmlGrammar methodsFor: 'token' stamp: 'lr 1/26/2010 09:15'! nameToken "[5] Name ::= NameStartChar (NameChar)*" ^ (nameStartChar , nameChar star) flatten! ! !PPXmlGrammar methodsFor: 'token' stamp: 'lr 1/26/2010 10:41'! nameTokens "[6] Names ::= Name (#x20 Name)*" ^ (nameToken separatedBy: $ asParser) flatten! ! !PPXmlGrammar methodsFor: 'token' stamp: 'lr 1/26/2010 09:17'! nmToken "[7] Nmtoken ::= (NameChar)+" ^ nameChar plus flatten! ! !PPXmlGrammar methodsFor: 'token' stamp: 'lr 1/26/2010 09:17'! nmTokens "[8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*" ^ (nmToken separatedBy: $ asParser) flatten! ! !PPXmlGrammar methodsFor: 'parsers' stamp: 'lr 1/26/2010 14:15'! parserForAttribute: aNameParser value: aValueParser "Answer a parser that can read an XML attribute." ^ aNameParser asParser flatten , whitespace optional , $= asParser , whitespace optional , $" asParser , aValueParser asParser , $" asParser ==> [ :nodes | nodes first -> nodes sixth ]! ! !PPXmlGrammar methodsFor: 'parsers-tags' stamp: 'lr 1/29/2010 13:47'! parserForCloseTag: aNameParser "Answer a parser that parses an XML element named aNameParser close-tag. This parser answers the name of the tag." ^ ' asParser ==> #second! ! !PPXmlGrammar methodsFor: 'parsers-tags' stamp: 'lr 2/4/2010 13:30'! parserForContentTag: aNameParser attributes: anAttributeParser content: aContentParser "Answer a parser that parses an XML element named aNameParser with the attributes anAttributeParser (expected to answer a dictionary). This parser answers instances of PPXmlElement." ^ (self parserForOpenTag: aNameParser attributes: anAttributeParser) , (aContentParser asParser) , [ :stream | stream position ] asParser , (self parserForCloseTag: aNameParser) ==> [ :nodes | nodes first tag = nodes last ifTrue: [ nodes first setContents: nodes second ] ifFalse: [ PPFailure reason: 'Expected but got ' at: nodes third ] ]! ! !PPXmlGrammar methodsFor: 'parsers' stamp: 'lr 2/4/2010 13:31'! parserForDocument: anElementParser "Answer a parser that can read an XML document." ^ (self parserForProcessingInstruction: 'xml') , misc , (doctype flatten , misc) optional , anElementParser asParser , misc ==> [ :nodes | PPXmlDocument new setXmlDeclaration: nodes first; setDocumentType: (nodes third isNil ifFalse: [ nodes third first ]); setRootElement: nodes fourth; yourself ]! ! !PPXmlGrammar methodsFor: 'parsers' stamp: 'lr 2/4/2010 16:06'! parserForElement: anElement ^ characterData optional , ((anElement / processing / comment) , characterData optional) star ==> [ :nodes | | result | result := OrderedCollection new. nodes first isNil ifFalse: [ result addLast: nodes first ]. nodes second do: [ :each | result addLast: each first. each second isNil ifFalse: [ result addLast: each second ] ]. result ]! ! !PPXmlGrammar methodsFor: 'parsers-tags' stamp: 'lr 1/29/2010 13:53'! parserForEmptyTag: aNameParser attributes: anAttributeParser "Answer a parser that parses an XML element named aNameParser with the attributes anAttributeParser (expected to answer a dictionary). This parser answers instances of PPXmlElement." ^ $< asParser , (PPXmlQualifiedParser local: aNameParser) , (anAttributeParser asParser) , whitespace optional , '/>' asParser ==> [ :nodes | PPXmlElement tag: nodes second attributes: nodes third ]! ! !PPXmlGrammar methodsFor: 'parsers-tags' stamp: 'lr 1/29/2010 13:53'! parserForOpenTag: aNameParser attributes: anAttributeParser "Answer a parser that parses an XML element named aNameParser with the attributes anAttributeParser (expected to answer a dictionary). This parser answers instances of PPXmlElement." ^ $< asParser , (PPXmlQualifiedParser local: aNameParser) , (anAttributeParser asParser) , whitespace optional , $> asParser ==> [ :nodes | PPXmlElement tag: nodes second attributes: nodes third ]! ! !PPXmlGrammar methodsFor: 'parsers' stamp: 'lr 2/7/2010 20:23'! parserForProcessingInstruction: aTargetParser "Answer a parser that can read an XML processing instruction." ^ '' asParser negate star token) optional flatten, '?>' asParser ==> [ :nodes | PPXmlProcessing target: nodes second data: nodes third ]! ! !PPXmlGrammar methodsFor: 'parsers' stamp: 'lr 1/26/2010 13:01'! parserForRootElement ^ element! ! !PPXmlGrammar methodsFor: 'parsers-tags' stamp: 'lr 1/26/2010 16:34'! parserForTag: aNameParser attributes: anAttributeParser "Answer a parser that reads an empty XML tag. This parser answers instances of PPXmlElement." ^ self parserForTag: aNameParser attributes: anAttributeParser content: nil! ! !PPXmlGrammar methodsFor: 'parsers-tags' stamp: 'lr 1/29/2010 13:45'! parserForTag: aNameParser attributes: anAttributeParser content: aContentParser "Answer a parser that can read the XML tags." ^ aContentParser isNil ifTrue: [ self parserForEmptyTag: aNameParser attributes: anAttributeParser ] ifFalse: [ self parserForContentTag: aNameParser attributes: anAttributeParser content: aContentParser ]! ! !PPXmlGrammar methodsFor: 'grammar-misc' stamp: 'lr 1/26/2010 16:21'! processing "[16] PI ::= '' Char*)))? '?>' [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))" ^ self parserForProcessingInstruction: #letter asParser plus! ! !PPXmlGrammar methodsFor: 'accessing' stamp: 'lr 1/26/2010 09:25'! start ^ document end! ! !PPXmlGrammar methodsFor: 'accessing' stamp: 'lr 1/26/2010 11:45'! tokenParser ^ PPXmlTokenParser! ! !PPXmlGrammar methodsFor: 'grammar-misc' stamp: 'lr 1/26/2010 08:46'! whitespace "[3] S ::= (#x20 | #x9 | #xD | #xA)+" ^ #space asParser plus! ! PPXmlGrammar subclass: #PPXmlXsdGrammar instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Core'! !PPXmlXsdGrammar methodsFor: 'parsers' stamp: 'lr 2/4/2010 15:42'! parserForRootElement ^ self parserForContentTag: 'schema' attributes: attributes content: content! ! PPDelegateParser subclass: #PPXmlQualifiedParser instanceVariableNames: 'prefix local' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Support'! !PPXmlQualifiedParser class methodsFor: 'instance creation' stamp: 'lr 1/29/2010 12:38'! local: aParser ^ self basicNew local: aParser! ! !PPXmlQualifiedParser methodsFor: 'accessing' stamp: 'lr 1/29/2010 12:38'! local: aParser local := aParser asParser. self update! ! !PPXmlQualifiedParser methodsFor: 'accessing' stamp: 'lr 1/29/2010 12:36'! prefix: aParser prefix := aParser asParser. self update! ! !PPXmlQualifiedParser methodsFor: 'updating' stamp: 'lr 2/4/2010 16:10'! update parser := prefix isNil ifTrue: [ local ] ifFalse: [ parser := prefix , $: asParser , local ]. parser := parser flatten ==> [ :value | (value includes: $:) ifTrue: [ value copyAfterLast: $: ] ifFalse: [ value ] ]! ! TestCase subclass: #PPXmlTest instanceVariableNames: 'result' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Tests'! PPXmlTest subclass: #PPXmlGrammarTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Tests'! !PPXmlGrammarTest methodsFor: 'accessing' stamp: 'TestRunner 1/7/2010 14:03'! parserClass ^ PPXmlGrammar! ! !PPXmlGrammarTest methodsFor: 'testing' stamp: 'lr 2/4/2010 14:13'! testParseAllXml self resource allXmlDefinitions do: [ :each | self assertParseInvariant: each ]! ! !PPXmlGrammarTest methodsFor: 'testing-specific' stamp: 'lr 2/4/2010 13:43'! testParseComment self assertParseInvariant: '' ! ! !PPXmlGrammarTest methodsFor: 'testing-specific' stamp: 'lr 2/4/2010 13:43'! testParseCommentWithXml self assertParseInvariant: ' -->' ! ! !PPXmlGrammarTest methodsFor: 'testing-specific' stamp: 'lr 2/4/2010 13:43'! testParseComplicated self assertParseInvariant: ' ' ! ! !PPXmlGrammarTest methodsFor: 'testing-specific' stamp: 'lr 2/4/2010 14:12'! testParseDoctype self assertParseInvariant: ' [ ] > '! ! !PPXmlGrammarTest methodsFor: 'testing-specific' stamp: 'lr 2/4/2010 13:43'! testParseEmptyElement self assertParseInvariant: '' ! ! !PPXmlGrammarTest methodsFor: 'testing-specific' stamp: 'lr 2/4/2010 13:43'! testParseNamespace self assertParseInvariant: '' ! ! !PPXmlGrammarTest methodsFor: 'testing-specific' stamp: 'lr 2/4/2010 13:43'! testParseSimple self assertParseInvariant: '' ! ! !PPXmlGrammarTest methodsFor: 'testing-specific' stamp: 'lr 2/4/2010 13:43'! testParseSimpleAttribute self assertParseInvariant: '' ! ! !PPXmlGrammarTest methodsFor: 'testing-specific' stamp: 'lr 2/4/2010 13:59'! testParseWithWhitsepaceAfterProlog self assertParseInvariant: ' ' ! ! PPXmlTest subclass: #PPXmlShiporderTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Tests'! !PPXmlShiporderTest methodsFor: 'accessing' stamp: 'lr 2/1/2010 12:04'! parserClass ^ PPXmlXsdGrammar! ! !PPXmlTest class methodsFor: 'testing' stamp: 'lr 1/26/2010 13:12'! isAbstract ^ self name = #PPXmlTest! ! !PPXmlTest class methodsFor: 'accessing' stamp: 'lr 1/7/2010 13:40'! packageNamesUnderTest ^ #('PetitXml')! ! !PPXmlTest class methodsFor: 'accessing' stamp: 'lr 1/7/2010 13:41'! resources ^ Array with: PPXmlResource! ! !PPXmlTest methodsFor: 'utilities' stamp: 'lr 2/7/2010 20:54'! assertParseInvariant: aString "Assert that aString can be parsed, serialized and parsed again to the same tree." | tree string | tree := self parse: aString. self deny: tree isPetitFailure description: tree printString. self assertTreeInvariant: tree. string := String streamContents: [ :out | tree printXmlOn: out ]. self assert: (self parse: string) = tree description: 'Parse invariant not satisifed'! ! !PPXmlTest methodsFor: 'utilities' stamp: 'lr 2/4/2010 13:52'! assertTreeInvariant: anXmlNode "Assert that anXmlNode is properly setup.." anXmlNode nodesDo: [ :node | | current children | node isDocument ifTrue: [ self assert: node parentNode isNil ] ifFalse: [ self assert: node parentNode notNil ]. node childNodes do: [ :child | self assert: child parentNode == node ]. current := node firstChild. children := OrderedCollection withAll: node childNodes. [ current isNil ] whileFalse: [ self assert: children notEmpty. self assert: children removeFirst == current. current := current nextSibling ]. self assert: children isEmpty. current := node lastChild. children := OrderedCollection withAll: node childNodes. [ current isNil ] whileFalse: [ self assert: children notEmpty. self assert: children removeLast == current. current := current previousSibling ]. self assert: children isEmpty ]! ! !PPXmlTest methodsFor: 'parsing' stamp: 'lr 2/1/2010 11:15'! parse: aString ^ self parse: aString rule: #start! ! !PPXmlTest methodsFor: 'parsing' stamp: 'lr 2/7/2010 20:51'! parse: aString rule: aSymbol | production | production := self parser. aSymbol = #start ifFalse: [ production := production instVarNamed: aSymbol ]. ^ production end parse: aString! ! !PPXmlTest methodsFor: 'accessing' stamp: 'lr 1/7/2010 13:56'! parser ^ self resource parserAt: self parserClass! ! !PPXmlTest methodsFor: 'accessing' stamp: 'lr 1/7/2010 13:41'! parserClass self subclassResponsibility! ! !PPXmlTest methodsFor: 'accessing' stamp: 'TestRunner 1/7/2010 14:03'! resource ^ PPXmlResource current! ! PPXmlTest subclass: #PPXmlXsdGrammarTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'PetitXml-Tests'! !PPXmlXsdGrammarTest methodsFor: 'accessing' stamp: 'lr 1/26/2010 12:58'! parserClass ^ PPXmlXsdGrammar! ! !PPXmlXsdGrammarTest methodsFor: 'testing' stamp: 'lr 2/4/2010 15:41'! testParseAll self resource allXsdDefinitions do: [ :each | self assertParseInvariant: each ]! !