1403 lines
33 KiB
Smalltalk
1403 lines
33 KiB
Smalltalk
![]() |
Object subclass: SoConstants [
|
|||
|
|
|||
|
<category: 'SoXML-Base'>
|
|||
|
<comment: 'Abstract Constants provider.
---
mu 5/3/2001 19:22'>
|
|||
|
|
|||
|
SoConstants class [
|
|||
|
| constDict |
|
|||
|
|
|||
|
]
|
|||
|
|
|||
|
SoConstants class >> at: aKey ifAbsentPutValue: aValue [
|
|||
|
<category: 'private'>
|
|||
|
^self constDict at: aKey ifAbsent: [self constDict at: aKey put: aValue]
|
|||
|
]
|
|||
|
|
|||
|
SoConstants class >> constDict [
|
|||
|
<category: 'accessing'>
|
|||
|
constDict isNil
|
|||
|
ifTrue:
|
|||
|
[constDict := (super canUnderstand: #constDict)
|
|||
|
ifTrue: [super constDict copy]
|
|||
|
ifFalse: [IdentityDictionary new]].
|
|||
|
^constDict
|
|||
|
]
|
|||
|
|
|||
|
SoConstants class >> initialize [
|
|||
|
"SoConstants initialize"
|
|||
|
|
|||
|
<category: 'class initialization'>
|
|||
|
constDict := nil
|
|||
|
]
|
|||
|
|
|||
|
SoConstants class >> removeKey: aKey [
|
|||
|
<category: 'private'>
|
|||
|
^self constDict removeKey: aKey
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SoConstants subclass: SoXmlConstants [
|
|||
|
|
|||
|
<category: 'SoXML-Base'>
|
|||
|
<comment: 'XML Constants provider.
(I hate to use Pool)
---
mu 5/3/2001 19:22'>
|
|||
|
|
|||
|
SoXmlConstants class >> anyType [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #anyType ifAbsentPutValue: 'anyType'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> base64 [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #base64 ifAbsentPutValue: 'base64'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> base64Binary [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #base64Binary ifAbsentPutValue: 'base64Binary'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> boolean [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #boolean ifAbsentPutValue: 'boolean'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> float [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #float ifAbsentPutValue: 'float'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> integer [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #integer ifAbsentPutValue: 'integer'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> string [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #string ifAbsentPutValue: 'string'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> time [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #time ifAbsentPutValue: 'time'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> withColon: aString [
|
|||
|
<category: 'utility'>
|
|||
|
| wStr |
|
|||
|
wStr := WriteStream on: (String new: aString size).
|
|||
|
wStr nextPutAll: aString.
|
|||
|
wStr nextPut: $:.
|
|||
|
^wStr contents
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xmlnsPrefix [
|
|||
|
<category: 'prefixes'>
|
|||
|
^self at: #xmlnsPrefix ifAbsentPutValue: 'xmlns'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xmlnsPrefixColon [
|
|||
|
<category: 'prefixes'>
|
|||
|
^self withColon: self xmlnsPrefix
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xmlnsURI [
|
|||
|
<category: 'URIs'>
|
|||
|
^self at: #xmlnsURI ifAbsentPutValue: 'http://www.w3.org/2000/xmlns/'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xmlnsURI: aString [
|
|||
|
<category: 'URIs'>
|
|||
|
^self constDict at: #xmlnsURI put: aString
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdAnyType [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #xsdAnyType ifAbsentPutValue: self xsdPrefixColon , 'anyType'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdBase64BinaryType [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #xsdBase64Binary
|
|||
|
ifAbsentPutValue: self xsdPrefixColon , 'base64Binary'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdFloatType [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #xsdFloatType ifAbsentPutValue: self xsdPrefixColon , 'float'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdIntegerType [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #xsdIntegerType ifAbsentPutValue: self xsdPrefixColon , 'integer'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdPrefix [
|
|||
|
<category: 'prefixes'>
|
|||
|
^self at: #xsdPrefix ifAbsentPutValue: 'xsd'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdPrefixColon [
|
|||
|
<category: 'prefixes'>
|
|||
|
^self withColon: self xsdPrefix
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdStringType [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #xsdStringType ifAbsentPutValue: self xsdPrefixColon , 'string'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdTimeType [
|
|||
|
<category: 'xsd types'>
|
|||
|
^self at: #xsdTime ifAbsentPutValue: self xsdPrefixColon , 'time'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdURI [
|
|||
|
<category: 'URIs'>
|
|||
|
^self at: #xsdURI ifAbsentPutValue: 'http://www.w3.org/2001/XMLSchema'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsdURI: aString [
|
|||
|
<category: 'URIs'>
|
|||
|
^self constDict at: #xsdURI put: aString
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsiPrefix [
|
|||
|
<category: 'prefixes'>
|
|||
|
^self at: #xsiPrefix ifAbsentPutValue: 'xsi'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsiPrefixColon [
|
|||
|
<category: 'prefixes'>
|
|||
|
^self withColon: self xsiPrefix
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsiType [
|
|||
|
"shortcut for performance"
|
|||
|
|
|||
|
<category: 'attributes'>
|
|||
|
^self at: #xsiType ifAbsentPutValue: self xsiPrefixColon , 'type'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsiURI [
|
|||
|
<category: 'URIs'>
|
|||
|
^self at: #xsiURI
|
|||
|
ifAbsentPutValue: 'http://www.w3.org/2001/XMLSchema-instance'
|
|||
|
]
|
|||
|
|
|||
|
SoXmlConstants class >> xsiURI: aString [
|
|||
|
<category: 'URIs'>
|
|||
|
^self constDict at: #xsiURI put: aString
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Object subclass: SoExoboxXMLParserAdapter [
|
|||
|
|
|||
|
<category: 'SoXML-ParserAdapter'>
|
|||
|
<comment: nil>
|
|||
|
|
|||
|
SoExoboxXMLParserAdapter class >> attribDictFrom: aParsedXMLElement [
|
|||
|
<category: 'actions'>
|
|||
|
aParsedXMLElement isText ifTrue: [^Dictionary new].
|
|||
|
^aParsedXMLElement attributes
|
|||
|
]
|
|||
|
|
|||
|
SoExoboxXMLParserAdapter class >> elementNameFrom: aParsedXMLElement [
|
|||
|
"assuming Exobox"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement tag
|
|||
|
]
|
|||
|
|
|||
|
SoExoboxXMLParserAdapter class >> elementShortNameFrom: aParsedXMLElement [
|
|||
|
<category: 'actions'>
|
|||
|
^(SoXmlUtil prefixAndLocalNameFrom: aParsedXMLElement tag) last
|
|||
|
]
|
|||
|
|
|||
|
SoExoboxXMLParserAdapter class >> elementValueFrom: aParsedXMLElement [
|
|||
|
<category: 'actions'>
|
|||
|
| cData |
|
|||
|
cData := aParsedXMLElement charactersData.
|
|||
|
^cData isEmpty ifTrue: [nil] ifFalse: [cData]
|
|||
|
]
|
|||
|
|
|||
|
SoExoboxXMLParserAdapter class >> elementsFrom: aParsedXMLElement [
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement contents
|
|||
|
]
|
|||
|
|
|||
|
SoExoboxXMLParserAdapter class >> elementsWithoutBlankTextsFrom: aParsedXMLElement [
|
|||
|
<category: 'actions'>
|
|||
|
aParsedXMLElement isText ifTrue: [^#()].
|
|||
|
^aParsedXMLElement contents
|
|||
|
reject: [:e | e isText and: [SoPortableUtil isBlank: e text]]
|
|||
|
]
|
|||
|
|
|||
|
SoExoboxXMLParserAdapter class >> elementsWithoutTextsFrom: aParsedXMLElement [
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement contents select: [:e | e isText not]
|
|||
|
]
|
|||
|
|
|||
|
SoExoboxXMLParserAdapter class >> isTextElement: aParsedXMLElement [
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement isText
|
|||
|
]
|
|||
|
|
|||
|
SoExoboxXMLParserAdapter class >> parseXml: xmlString [
|
|||
|
"assuming Exobox"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^(XMLReader fromString: xmlString) root
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Object subclass: SoPortableUtil [
|
|||
|
|
|||
|
<category: 'SoXML-Base'>
|
|||
|
<comment: 'An utility for providing adapter interfaces for various Smalltalk implementations.
Currently I support Squeak only.
If you would like to use other Smalltalks, you should subclass me.
---
mu 5/3/2001 19:23'>
|
|||
|
|
|||
|
SoPortableUtil class >> convertString: aString from: encoderName [
|
|||
|
<category: 'actions'>
|
|||
|
^aString
|
|||
|
convertFromWithConverter: (TextConverter newForEncoding: encoderName)
|
|||
|
]
|
|||
|
|
|||
|
SoPortableUtil class >> convertString: aString to: encoderName [
|
|||
|
<category: 'actions'>
|
|||
|
^aString
|
|||
|
convertToWithConverter: (TextConverter newForEncoding: encoderName)
|
|||
|
]
|
|||
|
|
|||
|
SoPortableUtil class >> isBlank: aString [
|
|||
|
"##ANSI ST specific##"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aString allSatisfy: [:i | i isSeparator]
|
|||
|
]
|
|||
|
|
|||
|
SoPortableUtil class >> relativeURIFrom: aString [
|
|||
|
"SoPortableUtil relativeURIFrom: 'urn:target:1'"
|
|||
|
|
|||
|
"SoPortableUtil relativeURIFrom: 'http://localhost:80/target/1'"
|
|||
|
|
|||
|
"SoPortableUtil relativeURIFrom: '/target1/'"
|
|||
|
|
|||
|
"SoPortableUtil relativeURIFrom: 'target1'"
|
|||
|
|
|||
|
"SoPortableUtil relativeURIFrom: '/'"
|
|||
|
|
|||
|
"##Squeak specific##"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
| uriStr colonIdx schemeName slashIdx |
|
|||
|
aString isEmpty ifTrue: [^aString].
|
|||
|
uriStr := aString last = $/
|
|||
|
ifTrue: [aString copyFrom: 1 to: aString size - 1]
|
|||
|
ifFalse: [aString].
|
|||
|
colonIdx := uriStr indexOf: $:
|
|||
|
ifAbsent: [^(uriStr beginsWith: '/') ifTrue: [uriStr] ifFalse: ['/' , uriStr]].
|
|||
|
schemeName := aString copyFrom: 1 to: colonIdx - 1.
|
|||
|
(schemeName allSatisfy: [:each | each isLetter])
|
|||
|
ifTrue: [uriStr := uriStr copyFrom: colonIdx + 1 to: uriStr size].
|
|||
|
((uriStr at: 1) = $/ and: [(uriStr at: 2) = $/])
|
|||
|
ifTrue: [uriStr := uriStr copyFrom: 2 to: uriStr size].
|
|||
|
slashIdx := uriStr findString: '/' startingAt: 2.
|
|||
|
slashIdx = 0
|
|||
|
ifFalse: [uriStr := uriStr copyFrom: slashIdx to: uriStr size].
|
|||
|
^uriStr
|
|||
|
]
|
|||
|
|
|||
|
SoPortableUtil class >> stackTraceFrom: anError [
|
|||
|
<category: 'actions'>
|
|||
|
| ctx |
|
|||
|
ctx := [anError signalerContext shortStack] on: Error
|
|||
|
do: [:ex | ex return: ''].
|
|||
|
^ctx
|
|||
|
]
|
|||
|
|
|||
|
SoPortableUtil class >> substringsFrom: aString [
|
|||
|
"ToDo: Support other Smalltalks"
|
|||
|
|
|||
|
"##Squeak specific##"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
aString isNil ifTrue: [^#()].
|
|||
|
^aString substrings
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Object subclass: SoVWXMLParserAdapter [
|
|||
|
|
|||
|
<category: 'SoXML-ParserAdapter'>
|
|||
|
<comment: nil>
|
|||
|
|
|||
|
SoVWXMLParserAdapter class >> attribDictFrom: aParsedXMLElement [
|
|||
|
"TODO: support multi parser"
|
|||
|
|
|||
|
"assuming VWXML"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
| dict |
|
|||
|
dict := Dictionary new.
|
|||
|
aParsedXMLElement isText ifTrue: [^dict].
|
|||
|
aParsedXMLElement attributes
|
|||
|
do: [:each | dict add: (Association key: each tag asString value: each value)].
|
|||
|
^dict
|
|||
|
]
|
|||
|
|
|||
|
SoVWXMLParserAdapter class >> elementNameFrom: aParsedXMLElement [
|
|||
|
"TODO: support multi parser"
|
|||
|
|
|||
|
"assuming VWXML"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement tag asString
|
|||
|
]
|
|||
|
|
|||
|
SoVWXMLParserAdapter class >> elementShortNameFrom: aParsedXMLElement [
|
|||
|
"TODO: support multi parser"
|
|||
|
|
|||
|
"assuming VWXML"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement tag type
|
|||
|
]
|
|||
|
|
|||
|
SoVWXMLParserAdapter class >> elementValueFrom: aParsedXMLElement [
|
|||
|
"TODO: support multi parser"
|
|||
|
|
|||
|
"assuming VWXML"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement isText
|
|||
|
ifTrue: [aParsedXMLElement characterData]
|
|||
|
ifFalse: [nil]
|
|||
|
]
|
|||
|
|
|||
|
SoVWXMLParserAdapter class >> elementsFrom: aParsedXMLElement [
|
|||
|
"TODO: support multi parser"
|
|||
|
|
|||
|
"assuming VWXML"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement elements
|
|||
|
]
|
|||
|
|
|||
|
SoVWXMLParserAdapter class >> elementsWithoutBlankTextsFrom: aParsedXMLElement [
|
|||
|
"TODO: support multi parser"
|
|||
|
|
|||
|
"assuming VWXML"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
aParsedXMLElement isText ifTrue: [^#()].
|
|||
|
^aParsedXMLElement elements
|
|||
|
reject: [:e | e isText and: [SoPortableUtil isBlank: e characterData]]
|
|||
|
]
|
|||
|
|
|||
|
SoVWXMLParserAdapter class >> elementsWithoutTextsFrom: aParsedXMLElement [
|
|||
|
"TODO: support multi parser"
|
|||
|
|
|||
|
"assuming VWXML"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement elements select: [:e | e isText not]
|
|||
|
]
|
|||
|
|
|||
|
SoVWXMLParserAdapter class >> isTextElement: aParsedXMLElement [
|
|||
|
"TODO: support multi parser"
|
|||
|
|
|||
|
"assuming VWXML"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement isText
|
|||
|
]
|
|||
|
|
|||
|
SoVWXMLParserAdapter class >> parseXml: xmlString [
|
|||
|
"TODO: support multi parser"
|
|||
|
|
|||
|
"assuming VWXML"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^(VWXMLXMLParser processDocumentString: xmlString
|
|||
|
beforeScanDo: [:p | p validate: false]) root
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Object subclass: SoXmlAttributesHolder [
|
|||
|
| namespaceDict otherDict |
|
|||
|
|
|||
|
<category: 'SoXML-Base'>
|
|||
|
<comment: 'An utitily class for XML attribute handling.
---
mu 5/3/2001 19:22'>
|
|||
|
|
|||
|
SoXmlAttributesHolder class >> new [
|
|||
|
<category: 'instance creation'>
|
|||
|
^super new initialize
|
|||
|
]
|
|||
|
|
|||
|
asDictionary [
|
|||
|
<category: 'actions'>
|
|||
|
| dict |
|
|||
|
dict := Dictionary new.
|
|||
|
self namespaceDict keysAndValuesDo: [:k :v | dict at: k put: v].
|
|||
|
self otherDict keysAndValuesDo: [:k :v | dict at: k put: v].
|
|||
|
^dict
|
|||
|
]
|
|||
|
|
|||
|
chopPrefix: attribName [
|
|||
|
<category: 'private'>
|
|||
|
^(SoXmlUtil prefixAndLocalNameFrom: attribName) last
|
|||
|
]
|
|||
|
|
|||
|
declareNamespace: prefix uri: uri [
|
|||
|
<category: 'actions'>
|
|||
|
prefix isEmpty
|
|||
|
ifTrue: [self namespaceDict at: SoXmlConstants xmlnsPrefix , prefix put: uri]
|
|||
|
ifFalse:
|
|||
|
[self namespaceDict at: SoXmlConstants xmlnsPrefixColon , prefix put: uri]
|
|||
|
]
|
|||
|
|
|||
|
declaredNamespacePrefixes [
|
|||
|
<category: 'actions'>
|
|||
|
^self namespaceDict keys collect:
|
|||
|
[:each |
|
|||
|
each = SoXmlConstants xmlnsPrefix
|
|||
|
ifTrue: ['']
|
|||
|
ifFalse:
|
|||
|
[each copyFrom: SoXmlConstants xmlnsPrefixColon size + 1 to: each size]]
|
|||
|
]
|
|||
|
|
|||
|
declaredNamespaceURIFor: prefix [
|
|||
|
<category: 'actions'>
|
|||
|
^self declaredNamespaceURIFor: prefix ifAbsent: []
|
|||
|
]
|
|||
|
|
|||
|
declaredNamespaceURIFor: prefix ifAbsent: aBlock [
|
|||
|
<category: 'actions'>
|
|||
|
^self namespaceDict at: SoXmlConstants xmlnsPrefixColon , prefix
|
|||
|
ifAbsent: [self namespaceDict at: SoXmlConstants xmlnsPrefix ifAbsent: aBlock]
|
|||
|
]
|
|||
|
|
|||
|
getAttributeLike: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
| key |
|
|||
|
key := self otherDict keys detect: [:each | aNameString match: each]
|
|||
|
ifNone: [].
|
|||
|
key isNil
|
|||
|
ifTrue:
|
|||
|
[key := self namespaceDict keys detect: [:each | aNameString match: each]
|
|||
|
ifNone: []].
|
|||
|
^self getAttributeNamed: key
|
|||
|
]
|
|||
|
|
|||
|
getAttributeNamed: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
^self otherDict at: aNameString
|
|||
|
ifAbsent: [self namespaceDict at: aNameString ifAbsent: []]
|
|||
|
]
|
|||
|
|
|||
|
hasAttributeLike: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
^(self otherDict keys detect: [:each | aNameString match: each]
|
|||
|
ifNone: [nil]) notNil
|
|||
|
or:
|
|||
|
[(self namespaceDict keys detect: [:each | aNameString match: each]
|
|||
|
ifNone: [nil]) notNil]
|
|||
|
]
|
|||
|
|
|||
|
hasAttributeNamed: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
^(self otherDict includesKey: aNameString)
|
|||
|
or: [self namespaceDict includesKey: aNameString]
|
|||
|
]
|
|||
|
|
|||
|
initialize [
|
|||
|
<category: 'initialize-release'>
|
|||
|
namespaceDict := Dictionary new.
|
|||
|
otherDict := Dictionary new
|
|||
|
]
|
|||
|
|
|||
|
namespaceDict [
|
|||
|
<category: 'accessing'>
|
|||
|
^namespaceDict
|
|||
|
]
|
|||
|
|
|||
|
otherDict [
|
|||
|
<category: 'accessing'>
|
|||
|
^otherDict
|
|||
|
]
|
|||
|
|
|||
|
printOn: aStream [
|
|||
|
"super printOn: aStream."
|
|||
|
|
|||
|
"for Debug"
|
|||
|
|
|||
|
<category: 'printing'>
|
|||
|
self printXmlOn: aStream
|
|||
|
]
|
|||
|
|
|||
|
printXmlOn: aStream [
|
|||
|
<category: 'printing'>
|
|||
|
self namespaceDict keysAndValuesDo:
|
|||
|
[:k :v |
|
|||
|
aStream nextPut: Character space.
|
|||
|
self writeName: k on: aStream.
|
|||
|
aStream nextPutAll: '="'.
|
|||
|
self writeValue: v asString on: aStream.
|
|||
|
aStream nextPut: $"].
|
|||
|
self otherDict keysAndValuesDo:
|
|||
|
[:k :v |
|
|||
|
aStream nextPut: Character space.
|
|||
|
self writeName: k on: aStream.
|
|||
|
aStream nextPutAll: '="'.
|
|||
|
self writeValue: v asString on: aStream.
|
|||
|
aStream nextPut: $"]
|
|||
|
]
|
|||
|
|
|||
|
putAttribute: aNameValueArray [
|
|||
|
<category: 'actions'>
|
|||
|
self putAttributeNamed: aNameValueArray first asString
|
|||
|
value: aNameValueArray last asString
|
|||
|
]
|
|||
|
|
|||
|
putAttributeNamed: attribName value: attribValue [
|
|||
|
<category: 'actions'>
|
|||
|
((attribName beginsWith: SoXmlConstants xmlnsPrefixColon)
|
|||
|
or: [attribName = SoXmlConstants xmlnsPrefix])
|
|||
|
ifTrue: [self namespaceDict at: attribName put: attribValue]
|
|||
|
ifFalse: [self otherDict at: attribName put: attribValue]
|
|||
|
]
|
|||
|
|
|||
|
removeAttributeNamed: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
^self otherDict removeKey: aNameString
|
|||
|
]
|
|||
|
|
|||
|
trimAttributePrefixNamed: attribName [
|
|||
|
<category: 'actions'>
|
|||
|
| value newKey |
|
|||
|
value := self otherDict at: attribName ifAbsent: [].
|
|||
|
value isNil ifTrue: [^nil].
|
|||
|
newKey := self chopPrefix: attribName.
|
|||
|
self removeAttributeNamed: attribName.
|
|||
|
^self putAttributeNamed: newKey value: value
|
|||
|
]
|
|||
|
|
|||
|
undeclareNamespaces [
|
|||
|
<category: 'actions'>
|
|||
|
namespaceDict := Dictionary new
|
|||
|
]
|
|||
|
|
|||
|
writeName: aCharacterArray on: aStream [
|
|||
|
"TODO: check illegal characters"
|
|||
|
|
|||
|
<category: 'private'>
|
|||
|
^aStream nextPutAll: aCharacterArray
|
|||
|
]
|
|||
|
|
|||
|
writeValue: aCharacterArray on: aStream [
|
|||
|
<category: 'private'>
|
|||
|
^SoXmlUtil writeXmlText: aCharacterArray on: aStream
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Object subclass: SoXmlUtil [
|
|||
|
|
|||
|
<category: 'SoXML-Base'>
|
|||
|
<comment: 'An utility for XML processing.
It includes:
-Parsing XML
-Writing XML text
I assume you have VWXMLParser.
If you would like to use other XML parsers, you should subclass me.
---
mu 5/3/2001 19:23'>
|
|||
|
|
|||
|
SoXmlUtil class [
|
|||
|
| convertCharDict parserAdapter useNcr stringEncoding |
|
|||
|
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> asXmlText: aString [
|
|||
|
<category: 'actions'>
|
|||
|
| wStr |
|
|||
|
wStr := WriteStream on: (String new: aString size).
|
|||
|
^(self writeXmlText: aString on: wStr) contents
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> attribDictFrom: aParsedXMLElement [
|
|||
|
<category: 'actions-parse'>
|
|||
|
^self parserAdapter attribDictFrom: aParsedXMLElement
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> contentsWithXmlDeclaration: aString [
|
|||
|
<category: 'actions'>
|
|||
|
| wStr |
|
|||
|
wStr := WriteStream on: (String new: 1024).
|
|||
|
wStr
|
|||
|
nextPutAll: '<?xml version="1.0" encoding="' , self stringEncoding , '"?>'.
|
|||
|
2 timesRepeat:
|
|||
|
[wStr nextPut: Character cr.
|
|||
|
wStr nextPut: Character lf].
|
|||
|
wStr nextPutAll: aString.
|
|||
|
^SoPortableUtil convertString: wStr contents to: self stringEncoding
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> convertCharDict [
|
|||
|
<category: 'accessing'>
|
|||
|
^convertCharDict
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> elementNameFrom: aParsedXMLElement [
|
|||
|
<category: 'actions-parse'>
|
|||
|
^self parserAdapter elementNameFrom: aParsedXMLElement
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> elementShortNameFrom: aParsedXMLElement [
|
|||
|
<category: 'actions-parse'>
|
|||
|
^self parserAdapter elementShortNameFrom: aParsedXMLElement
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> elementValueFrom: aParsedXMLElement [
|
|||
|
<category: 'actions-parse'>
|
|||
|
^self parserAdapter elementValueFrom: aParsedXMLElement
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> elementsFrom: aParsedXMLElement [
|
|||
|
<category: 'actions-parse'>
|
|||
|
^self parserAdapter elementsFrom: aParsedXMLElement
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> elementsWithoutBlankTextsFrom: aParsedXMLElement [
|
|||
|
<category: 'actions-parse'>
|
|||
|
^self parserAdapter elementsWithoutBlankTextsFrom: aParsedXMLElement
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> elementsWithoutTextsFrom: aParsedXMLElement [
|
|||
|
<category: 'actions-parse'>
|
|||
|
^self parserAdapter elementsWithoutTextsFrom: aParsedXMLElement
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> initConvertCharDict [
|
|||
|
<category: 'private-initialize'>
|
|||
|
convertCharDict := Dictionary new.
|
|||
|
0 to: 47
|
|||
|
do: [:each | convertCharDict at: each put: '&#' , each asString , ';'].
|
|||
|
convertCharDict
|
|||
|
at: $& asciiValue put: '&';
|
|||
|
at: $< asciiValue put: '<';
|
|||
|
at: $> asciiValue put: '>';
|
|||
|
at: $' asciiValue put: ''';
|
|||
|
at: $" asciiValue put: '"'.
|
|||
|
convertCharDict
|
|||
|
removeKey: Character space asciiValue;
|
|||
|
removeKey: Character tab asciiValue;
|
|||
|
removeKey: Character cr asciiValue;
|
|||
|
removeKey: Character lf asciiValue.
|
|||
|
convertCharDict
|
|||
|
removeKey: $/ asciiValue;
|
|||
|
removeKey: $- asciiValue;
|
|||
|
removeKey: $# asciiValue;
|
|||
|
removeKey: $. asciiValue
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> initParserAdapter [
|
|||
|
"Currently YAXO and VWXML conscious"
|
|||
|
|
|||
|
<category: 'private-initialize'>
|
|||
|
parserAdapter := self environment at: #SoYaxXMLParserAdapter
|
|||
|
ifAbsent:
|
|||
|
[self environment at: #SoVWXMLParserAdapter
|
|||
|
ifAbsent:
|
|||
|
[Transcript
|
|||
|
cr;
|
|||
|
show: '##failed to initParserAdapter##']]
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> initialize [
|
|||
|
"SoXmlUtil initialize"
|
|||
|
|
|||
|
<category: 'class initialization'>
|
|||
|
self initConvertCharDict.
|
|||
|
parserAdapter := nil
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> isPrefixedName: aString [
|
|||
|
"self isPrefixedName: 'aaa:bbb'"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
aString ifNil: [^false].
|
|||
|
^aString includes: $:
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> isTextElement: aParsedXMLElement [
|
|||
|
<category: 'actions-parse'>
|
|||
|
^self parserAdapter isTextElement: aParsedXMLElement
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> localNameFrom: aString [
|
|||
|
<category: 'actions'>
|
|||
|
aString ifNil: [^''].
|
|||
|
^(self prefixAndLocalNameFrom: aString) last
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> parseXml: xmlString [
|
|||
|
<category: 'actions-parse'>
|
|||
|
^self parserAdapter parseXml: xmlString
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> parserAdapter [
|
|||
|
<category: 'accessing'>
|
|||
|
parserAdapter ifNil: [self initParserAdapter].
|
|||
|
^parserAdapter
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> parserAdapter: xmlParserAdapter [
|
|||
|
<category: 'accessing'>
|
|||
|
parserAdapter := xmlParserAdapter
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> prefixAndLocalNameFrom: aString [
|
|||
|
<category: 'actions'>
|
|||
|
| index readStream prefixName localName |
|
|||
|
index := aString indexOf: $:.
|
|||
|
index = 0
|
|||
|
ifTrue:
|
|||
|
[prefixName := ''.
|
|||
|
localName := aString]
|
|||
|
ifFalse:
|
|||
|
[readStream := aString readStream.
|
|||
|
prefixName := readStream next: index - 1.
|
|||
|
readStream skip: 1.
|
|||
|
localName := readStream next: aString size - index].
|
|||
|
^Array with: prefixName with: localName
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> prefixFrom: aString [
|
|||
|
<category: 'actions'>
|
|||
|
aString ifNil: [^nil].
|
|||
|
^(self prefixAndLocalNameFrom: aString) first
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> randomPrefix [
|
|||
|
<category: 'actions'>
|
|||
|
^'ns' , (Random new nextInt: 100000000) printString
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> stringEncoding [
|
|||
|
<category: 'accessing'>
|
|||
|
stringEncoding ifNil: [stringEncoding := 'utf-8'].
|
|||
|
^stringEncoding
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> stringEncoding: aString [
|
|||
|
<category: 'accessing'>
|
|||
|
stringEncoding := aString
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> useNcr [
|
|||
|
<category: 'accessing'>
|
|||
|
useNcr ifNil: [useNcr := false].
|
|||
|
^useNcr
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> useNcr: aBoolean [
|
|||
|
<category: 'accessing'>
|
|||
|
useNcr := aBoolean == true
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> writeUnicodeChar: aCharacter code: charCode on: aWriteStream [
|
|||
|
<category: 'private'>
|
|||
|
self useNcr
|
|||
|
ifTrue:
|
|||
|
[aWriteStream
|
|||
|
nextPutAll: '&#';
|
|||
|
nextPutAll: charCode asString;
|
|||
|
nextPut: $;]
|
|||
|
ifFalse: [aWriteStream nextPut: aCharacter]
|
|||
|
]
|
|||
|
|
|||
|
SoXmlUtil class >> writeXmlText: aString on: aWriteStream [
|
|||
|
<category: 'actions'>
|
|||
|
| cDict wStr contentStr |
|
|||
|
cDict := self convertCharDict.
|
|||
|
wStr := aWriteStream.
|
|||
|
contentStr := aString asString.
|
|||
|
contentStr do:
|
|||
|
[:eachChar |
|
|||
|
| val |
|
|||
|
val := eachChar charCode.
|
|||
|
val >= 127
|
|||
|
ifTrue:
|
|||
|
[self
|
|||
|
writeUnicodeChar: eachChar
|
|||
|
code: val
|
|||
|
on: wStr]
|
|||
|
ifFalse:
|
|||
|
[| conv |
|
|||
|
conv := cDict at: val ifAbsent: [].
|
|||
|
conv isNil
|
|||
|
ifTrue: [wStr nextPut: eachChar]
|
|||
|
ifFalse: [wStr nextPutAll: conv]]].
|
|||
|
^wStr
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Object subclass: SoXmlWrapElement [
|
|||
|
| prefixName localName name value attributesHolder children parent isEmptyBody isPrintCDATA |
|
|||
|
|
|||
|
<category: 'SoXML-Base'>
|
|||
|
<comment: 'Representing an XML element.
Using XmlUtil, I am independent of XML parser implementations.
--
mu 5/3/2001 19:28'>
|
|||
|
|
|||
|
IsPrintCDATA := nil.
|
|||
|
|
|||
|
SoXmlWrapElement class >> emptyNamed: anElemName [
|
|||
|
<category: 'instance creation'>
|
|||
|
^(self named: anElemName) beEmpty
|
|||
|
]
|
|||
|
|
|||
|
SoXmlWrapElement class >> fromXml: xmlString [
|
|||
|
<category: 'from xml'>
|
|||
|
^self fromXmlElement: (SoXmlUtil parseXml: xmlString)
|
|||
|
]
|
|||
|
|
|||
|
SoXmlWrapElement class >> fromXmlElement: aParsedXmlElement [
|
|||
|
<category: 'from xml'>
|
|||
|
^self new initByDom: aParsedXmlElement
|
|||
|
]
|
|||
|
|
|||
|
SoXmlWrapElement class >> isPrintCDATA [
|
|||
|
<category: 'accessing'>
|
|||
|
IsPrintCDATA isNil ifTrue: [IsPrintCDATA := false].
|
|||
|
^IsPrintCDATA
|
|||
|
]
|
|||
|
|
|||
|
SoXmlWrapElement class >> isPrintCDATA: aBoolean [
|
|||
|
<category: 'accessing'>
|
|||
|
IsPrintCDATA := aBoolean
|
|||
|
]
|
|||
|
|
|||
|
SoXmlWrapElement class >> named: anElemName [
|
|||
|
<category: 'instance creation'>
|
|||
|
^self new name: anElemName
|
|||
|
]
|
|||
|
|
|||
|
SoXmlWrapElement class >> named: anElemName withPrefix: prefix [
|
|||
|
<category: 'instance creation'>
|
|||
|
prefix ifEmpty: [^self named: anElemName].
|
|||
|
^self named: prefix , ':' , anElemName
|
|||
|
]
|
|||
|
|
|||
|
SoXmlWrapElement class >> new [
|
|||
|
<category: 'instance creation'>
|
|||
|
^super new initialize
|
|||
|
]
|
|||
|
|
|||
|
addChild: anXMLEleemnt [
|
|||
|
<category: 'actions'>
|
|||
|
anXMLEleemnt isNil ifTrue: [^nil].
|
|||
|
anXMLEleemnt parent: self.
|
|||
|
^self children add: anXMLEleemnt
|
|||
|
]
|
|||
|
|
|||
|
allDeclaredNamespacePrefixes [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder declaredNamespacePrefixes
|
|||
|
ifNotEmptyDo: [:prefixes | prefixes]
|
|||
|
ifEmpty: [self parent ifNotNilDo: [:par | par declaredNamespacePrefixes]]
|
|||
|
]
|
|||
|
|
|||
|
allDeclaredNamespaceURIFor: prefix [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder declaredNamespaceURIFor: prefix
|
|||
|
ifAbsent:
|
|||
|
[self parent notNil ifTrue: [self parent declaredNamespaceURIFor: prefix]]
|
|||
|
]
|
|||
|
|
|||
|
attributesDictionary [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder asDictionary
|
|||
|
]
|
|||
|
|
|||
|
attributesHolder [
|
|||
|
<category: 'accessing'>
|
|||
|
attributesHolder isNil
|
|||
|
ifTrue: [attributesHolder := SoXmlAttributesHolder new].
|
|||
|
^attributesHolder
|
|||
|
]
|
|||
|
|
|||
|
attributesHolder: aValue [
|
|||
|
<category: 'accessing'>
|
|||
|
attributesHolder := aValue
|
|||
|
]
|
|||
|
|
|||
|
basicValue: aValue [
|
|||
|
"Exceptional Use: For debugging or performance tuning"
|
|||
|
|
|||
|
<category: 'accessing'>
|
|||
|
value := aValue
|
|||
|
]
|
|||
|
|
|||
|
beEmpty [
|
|||
|
<category: 'actions'>
|
|||
|
self isEmptyBody: true
|
|||
|
]
|
|||
|
|
|||
|
beShortName [
|
|||
|
<category: 'actions'>
|
|||
|
self name: self shortName
|
|||
|
]
|
|||
|
|
|||
|
children [
|
|||
|
<category: 'accessing'>
|
|||
|
children isNil ifTrue: [children := OrderedCollection new].
|
|||
|
^children
|
|||
|
]
|
|||
|
|
|||
|
children: aValue [
|
|||
|
<category: 'accessing'>
|
|||
|
children := aValue
|
|||
|
]
|
|||
|
|
|||
|
createChildNamed: anElemName [
|
|||
|
<category: 'actions'>
|
|||
|
| child |
|
|||
|
child := self class named: anElemName.
|
|||
|
self addChild: child.
|
|||
|
^child
|
|||
|
]
|
|||
|
|
|||
|
createParentNamed: anElemName [
|
|||
|
<category: 'actions'>
|
|||
|
| pa |
|
|||
|
pa := self class named: anElemName.
|
|||
|
pa addChild: self.
|
|||
|
^pa
|
|||
|
]
|
|||
|
|
|||
|
declareNamespace: prefix uri: uri [
|
|||
|
<category: 'actions'>
|
|||
|
self attributesHolder declareNamespace: prefix uri: uri
|
|||
|
]
|
|||
|
|
|||
|
declaredNamespacePrefixes [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder declaredNamespacePrefixes
|
|||
|
]
|
|||
|
|
|||
|
declaredNamespaceURIFor: prefix [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder declaredNamespaceURIFor: prefix
|
|||
|
]
|
|||
|
|
|||
|
findChild: aBlock [
|
|||
|
<category: 'actions'>
|
|||
|
^self children detect: aBlock ifNone: []
|
|||
|
]
|
|||
|
|
|||
|
findChildLocalNamed: anElemName [
|
|||
|
<category: 'actions'>
|
|||
|
^self children detect: [:each | each localName = anElemName] ifNone: []
|
|||
|
]
|
|||
|
|
|||
|
findChildNamed: anElemName [
|
|||
|
<category: 'actions'>
|
|||
|
^self children detect: [:each | each name = anElemName] ifNone: []
|
|||
|
]
|
|||
|
|
|||
|
findChildren: aBlock [
|
|||
|
<category: 'actions'>
|
|||
|
^self children select: aBlock
|
|||
|
]
|
|||
|
|
|||
|
findChildrenLocalNamed: anElemName [
|
|||
|
<category: 'actions'>
|
|||
|
^self children select: [:each | each localName = anElemName]
|
|||
|
]
|
|||
|
|
|||
|
findChildrenNamed: anElemName [
|
|||
|
<category: 'actions'>
|
|||
|
^self children select: [:each | each name = anElemName]
|
|||
|
]
|
|||
|
|
|||
|
firstChild [
|
|||
|
<category: 'actions'>
|
|||
|
^self children first
|
|||
|
]
|
|||
|
|
|||
|
getAttributeLike: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder getAttributeLike: aNameString
|
|||
|
]
|
|||
|
|
|||
|
getAttributeNamed: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder getAttributeNamed: aNameString
|
|||
|
]
|
|||
|
|
|||
|
hasAttributeLike: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder hasAttributeLike: aNameString
|
|||
|
]
|
|||
|
|
|||
|
hasAttributeNamed: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder hasAttributeNamed: aNameString
|
|||
|
]
|
|||
|
|
|||
|
initAttributesBy: aDictionary [
|
|||
|
<category: 'private-init'>
|
|||
|
aDictionary keysAndValuesDo: [:k :v | self putAttributeNamed: k value: v]
|
|||
|
]
|
|||
|
|
|||
|
initByDom: aParsedXmlElement [
|
|||
|
<category: 'private-init'>
|
|||
|
| prefixAndLocalName |
|
|||
|
self name: (SoXmlUtil elementNameFrom: aParsedXmlElement).
|
|||
|
prefixAndLocalName := SoXmlUtil prefixAndLocalNameFrom: self name.
|
|||
|
self prefixName: prefixAndLocalName first.
|
|||
|
self localName: prefixAndLocalName last.
|
|||
|
self initAttributesBy: (SoXmlUtil attribDictFrom: aParsedXmlElement).
|
|||
|
self value: (SoXmlUtil elementValueFrom: aParsedXmlElement).
|
|||
|
(SoXmlUtil elementsWithoutBlankTextsFrom: aParsedXmlElement)
|
|||
|
do: [:each | self initChildElementByDom: each]
|
|||
|
]
|
|||
|
|
|||
|
initChildElementByDom: aParsedXmlElement [
|
|||
|
<category: 'private-init'>
|
|||
|
| parentElem childElmClass child |
|
|||
|
(SoXmlUtil isTextElement: aParsedXmlElement)
|
|||
|
ifTrue: [^self value: (SoXmlUtil elementValueFrom: aParsedXmlElement)].
|
|||
|
parentElem := SoXmlUtil elementNameFrom: aParsedXmlElement.
|
|||
|
childElmClass := self privElementClassFrom: parentElem.
|
|||
|
child := childElmClass fromXmlElement: aParsedXmlElement.
|
|||
|
self addChild: child
|
|||
|
]
|
|||
|
|
|||
|
initialize [
|
|||
|
<category: 'initialize-release'>
|
|||
|
isEmptyBody := false
|
|||
|
]
|
|||
|
|
|||
|
isEmptyBody [
|
|||
|
<category: 'accessing'>
|
|||
|
^isEmptyBody
|
|||
|
]
|
|||
|
|
|||
|
isEmptyBody: aValue [
|
|||
|
<category: 'accessing'>
|
|||
|
isEmptyBody := aValue
|
|||
|
]
|
|||
|
|
|||
|
isPrintCDATA [
|
|||
|
<category: 'accessing'>
|
|||
|
isPrintCDATA isNil ifTrue: [isPrintCDATA := self class isPrintCDATA].
|
|||
|
^isPrintCDATA
|
|||
|
]
|
|||
|
|
|||
|
isPrintCDATA: aValue [
|
|||
|
<category: 'accessing'>
|
|||
|
isPrintCDATA := aValue
|
|||
|
]
|
|||
|
|
|||
|
isXmlPrintable [
|
|||
|
<category: 'private'>
|
|||
|
^self name notNil
|
|||
|
]
|
|||
|
|
|||
|
localName [
|
|||
|
<category: 'accessing'>
|
|||
|
^localName
|
|||
|
]
|
|||
|
|
|||
|
localName: aValue [
|
|||
|
<category: 'accessing'>
|
|||
|
localName := aValue
|
|||
|
]
|
|||
|
|
|||
|
name [
|
|||
|
<category: 'accessing'>
|
|||
|
^name
|
|||
|
]
|
|||
|
|
|||
|
name: aValue [
|
|||
|
<category: 'accessing'>
|
|||
|
name := aValue
|
|||
|
]
|
|||
|
|
|||
|
parent [
|
|||
|
<category: 'accessing'>
|
|||
|
^parent
|
|||
|
]
|
|||
|
|
|||
|
parent: aValue [
|
|||
|
<category: 'accessing'>
|
|||
|
parent := aValue
|
|||
|
]
|
|||
|
|
|||
|
prefixName [
|
|||
|
<category: 'accessing'>
|
|||
|
^prefixName
|
|||
|
]
|
|||
|
|
|||
|
prefixName: aValue [
|
|||
|
<category: 'accessing'>
|
|||
|
prefixName := aValue
|
|||
|
]
|
|||
|
|
|||
|
printOn: aStream [
|
|||
|
"super printOn: aStream"
|
|||
|
|
|||
|
"for Debug"
|
|||
|
|
|||
|
<category: 'printing'>
|
|||
|
self printXmlOn: aStream
|
|||
|
]
|
|||
|
|
|||
|
printXmlContentsOn: aStream indent: level [
|
|||
|
<category: 'printing'>
|
|||
|
self isEmptyBody
|
|||
|
ifFalse:
|
|||
|
[self value isNil ifFalse: [self privPrintXmlContentOn: aStream].
|
|||
|
children isNil
|
|||
|
ifFalse:
|
|||
|
["ugly - but for performance"
|
|||
|
|
|||
|
aStream cr.
|
|||
|
self privPrintChildrenOn: aStream indent: level + 1.
|
|||
|
level timesRepeat: [aStream space]]]
|
|||
|
]
|
|||
|
|
|||
|
printXmlFooterOn: aStream [
|
|||
|
<category: 'printing'>
|
|||
|
self isXmlPrintable ifFalse: [^self].
|
|||
|
self isEmptyBody
|
|||
|
ifFalse:
|
|||
|
[aStream nextPut: $<.
|
|||
|
aStream nextPut: $/.
|
|||
|
self writeName: self name on: aStream.
|
|||
|
aStream nextPut: $>]
|
|||
|
]
|
|||
|
|
|||
|
printXmlHeaderOn: aStream [
|
|||
|
<category: 'printing'>
|
|||
|
self isXmlPrintable ifFalse: [^self].
|
|||
|
self isEmptyBody
|
|||
|
ifTrue:
|
|||
|
[aStream nextPut: $<.
|
|||
|
self writeName: self name on: aStream.
|
|||
|
self privPrintAttribsOn: aStream.
|
|||
|
aStream nextPut: $/.
|
|||
|
aStream nextPut: $>]
|
|||
|
ifFalse:
|
|||
|
[aStream nextPut: $<.
|
|||
|
self writeName: self name on: aStream.
|
|||
|
self privPrintAttribsOn: aStream.
|
|||
|
aStream nextPut: $>]
|
|||
|
]
|
|||
|
|
|||
|
printXmlOn: aStream [
|
|||
|
<category: 'printing'>
|
|||
|
self printXmlOn: aStream indent: 0
|
|||
|
]
|
|||
|
|
|||
|
printXmlOn: aStream indent: level [
|
|||
|
<category: 'printing'>
|
|||
|
self isXmlPrintable ifFalse: [^self].
|
|||
|
level timesRepeat: [aStream space].
|
|||
|
self printXmlHeaderOn: aStream.
|
|||
|
self printXmlContentsOn: aStream indent: level.
|
|||
|
self printXmlFooterOn: aStream.
|
|||
|
aStream cr
|
|||
|
]
|
|||
|
|
|||
|
privElementClassFrom: parentXmlElement [
|
|||
|
"override to return apporopriate XmlWrapElement"
|
|||
|
|
|||
|
<category: 'private'>
|
|||
|
^self class
|
|||
|
]
|
|||
|
|
|||
|
privPrintAttribsOn: aStream [
|
|||
|
<category: 'private'>
|
|||
|
attributesHolder isNil ifTrue: [^self]. "ugly - but for performance"
|
|||
|
self attributesHolder printXmlOn: aStream
|
|||
|
]
|
|||
|
|
|||
|
privPrintChildrenOn: aStream indent: level [
|
|||
|
<category: 'private'>
|
|||
|
(self privSortChildren: children)
|
|||
|
do: [:each | each printXmlOn: aStream indent: level]
|
|||
|
]
|
|||
|
|
|||
|
privPrintXmlContentOn: aStream [
|
|||
|
<category: 'private'>
|
|||
|
self isPrintCDATA
|
|||
|
ifTrue:
|
|||
|
[aStream nextPutAll: '<![CDATA['.
|
|||
|
aStream nextPutAll: self value.
|
|||
|
aStream nextPutAll: ']]>']
|
|||
|
ifFalse: [self writeValue: self value on: aStream]
|
|||
|
]
|
|||
|
|
|||
|
privSortChildren: aCollectionOfXmlElement [
|
|||
|
"default do nothing"
|
|||
|
|
|||
|
<category: 'sorting'>
|
|||
|
^aCollectionOfXmlElement
|
|||
|
]
|
|||
|
|
|||
|
putAttribute: aNameValueArray [
|
|||
|
<category: 'actions'>
|
|||
|
self putAttributeNamed: aNameValueArray first asString
|
|||
|
value: aNameValueArray last asString
|
|||
|
]
|
|||
|
|
|||
|
putAttributeNamed: aNameString value: aValueString [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder putAttributeNamed: aNameString value: aValueString
|
|||
|
]
|
|||
|
|
|||
|
removeAttributeNamed: aNameString [
|
|||
|
<category: 'actions'>
|
|||
|
^self attributesHolder removeAttributeNamed: aNameString
|
|||
|
]
|
|||
|
|
|||
|
removeChild: anXMLEleemnt [
|
|||
|
<category: 'actions'>
|
|||
|
^self children remove: anXMLEleemnt ifAbsent: [nil]
|
|||
|
]
|
|||
|
|
|||
|
shortName [
|
|||
|
<category: 'actions'>
|
|||
|
| nm idx sz |
|
|||
|
nm := self name.
|
|||
|
idx := nm indexOf: $: ifAbsent: [^nm].
|
|||
|
sz := nm size.
|
|||
|
idx > sz ifTrue: [^nm].
|
|||
|
^nm copyFrom: idx + 1 to: sz
|
|||
|
]
|
|||
|
|
|||
|
undeclareNamespaces [
|
|||
|
<category: 'actions'>
|
|||
|
self attributesHolder undeclareNamespaces
|
|||
|
]
|
|||
|
|
|||
|
value [
|
|||
|
<category: 'accessing'>
|
|||
|
^value
|
|||
|
]
|
|||
|
|
|||
|
value: aValue [
|
|||
|
<category: 'accessing'>
|
|||
|
aValue isNil ifTrue: [^self].
|
|||
|
value := aValue asString
|
|||
|
]
|
|||
|
|
|||
|
writeName: aCharacterArray on: aStream [
|
|||
|
"TODO: check illegal characters"
|
|||
|
|
|||
|
<category: 'private'>
|
|||
|
^aStream nextPutAll: aCharacterArray
|
|||
|
]
|
|||
|
|
|||
|
writeValue: aCharacterArray on: aStream [
|
|||
|
<category: 'private'>
|
|||
|
^SoXmlUtil writeXmlText: aCharacterArray on: aStream
|
|||
|
]
|
|||
|
|
|||
|
xmlString [
|
|||
|
<category: 'printing'>
|
|||
|
| wStr |
|
|||
|
wStr := WriteStream on: (String new: 64).
|
|||
|
self printXmlOn: wStr.
|
|||
|
^wStr contents
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Object subclass: SoYaxXMLParserAdapter [
|
|||
|
|
|||
|
<category: 'SoXML-ParserAdapter'>
|
|||
|
<comment: nil>
|
|||
|
|
|||
|
SoYaxXMLParserAdapter class >> attribDictFrom: aParsedXMLElement [
|
|||
|
<category: 'actions'>
|
|||
|
aParsedXMLElement isText ifTrue: [^Dictionary new].
|
|||
|
^aParsedXMLElement attributes
|
|||
|
]
|
|||
|
|
|||
|
SoYaxXMLParserAdapter class >> elementNameFrom: aParsedXMLElement [
|
|||
|
"assuming Yax"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement tag
|
|||
|
]
|
|||
|
|
|||
|
SoYaxXMLParserAdapter class >> elementShortNameFrom: aParsedXMLElement [
|
|||
|
"assuming Yax"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^(SoXmlUtil prefixAndLocalNameFrom: aParsedXMLElement tag) last
|
|||
|
]
|
|||
|
|
|||
|
SoYaxXMLParserAdapter class >> elementValueFrom: aParsedXMLElement [
|
|||
|
"assuming Yax"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
| cData |
|
|||
|
cData := aParsedXMLElement characterData.
|
|||
|
^cData isEmpty ifTrue: [nil] ifFalse: [cData]
|
|||
|
]
|
|||
|
|
|||
|
SoYaxXMLParserAdapter class >> elementsFrom: aParsedXMLElement [
|
|||
|
"assuming YAXO"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement elements , aParsedXMLElement contents
|
|||
|
]
|
|||
|
|
|||
|
SoYaxXMLParserAdapter class >> elementsWithoutBlankTextsFrom: aParsedXMLElement [
|
|||
|
"assuming YAXO"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement elements , (aParsedXMLElement contents
|
|||
|
reject: [:each | SoPortableUtil isBlank: each characterData])
|
|||
|
]
|
|||
|
|
|||
|
SoYaxXMLParserAdapter class >> elementsWithoutTextsFrom: aParsedXMLElement [
|
|||
|
"assuming YAXO"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement elements
|
|||
|
]
|
|||
|
|
|||
|
SoYaxXMLParserAdapter class >> isTextElement: aParsedXMLElement [
|
|||
|
"assuming Yax"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^aParsedXMLElement isText
|
|||
|
]
|
|||
|
|
|||
|
SoYaxXMLParserAdapter class >> parseXml: xmlString [
|
|||
|
"assuming Yax"
|
|||
|
|
|||
|
<category: 'actions'>
|
|||
|
^(XMLDOMParser parseDocumentFrom: (ReadStream on: xmlString)) topElement
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Eval [
|
|||
|
SoConstants initialize.
|
|||
|
SoXmlUtil initialize
|
|||
|
]
|
|||
|
|