2011-02-18 23:03:16 +00:00
PackageLoader fileInPackage: 'XML-XMLParser' .
2011-03-06 09:38:23 +00:00
PackageLoader fileInPackage: 'Iconv' .
2011-02-18 23:03:16 +00:00
2011-02-18 11:31:26 +00:00
Object subclass: SoConstants [
<category: 'SoXML-Base'>
< c o m m e n t : '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
i f T r u e :
[constDict := (super canUnderstand: #constDict )
i f T r u e : [super constDict copy ]
i f F a l s e : [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'>
< c o m m e n t : '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
i f A b s e n t P u t V a l u e : '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
r e j e c t : [: 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'>
< c o m m e n t : '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'>
2011-03-20 09:41:33 +00:00
"No reason to decode a unicode string"
aString isUnicode ifTrue: [^ aString ].
2011-03-06 09:38:23 +00:00
^ aString asUnicodeString: encoderName
2011-02-18 11:31:26 +00:00
]
SoPortableUtil class >> convertString: aString to: encoderName [
<category: 'actions'>
2011-03-06 09:38:23 +00:00
^ I18N . EncodedString fromString: aString encoding: encoderName
2011-02-18 11:31:26 +00:00
]
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 = $/
i f T r u e : [aString copyFrom: 1 to: aString size - 1 ]
i f F a l s e : [aString ].
colonIdx := uriStr indexOf: $:
i f A b s e n t : [^ (uriStr beginsWith: '/' ) ifTrue: [uriStr ] ifFalse: ['/' , uriStr ]].
schemeName := aString copyFrom: 1 to: colonIdx - 1 .
(schemeName allSatisfy: [: each | each isLetter ])
i f T r u e : [uriStr := uriStr copyFrom: colonIdx + 1 to: uriStr size ].
((uriStr at: 1 ) = $/ and: [(uriStr at: 2 ) = $/ ])
i f T r u e : [uriStr := uriStr copyFrom: 2 to: uriStr size ].
slashIdx := uriStr findString: '/' startingAt: 2 .
slashIdx = 0
i f F a l s e : [uriStr := uriStr copyFrom: slashIdx to: uriStr size ].
^ uriStr
]
SoPortableUtil class >> stackTraceFrom: anError [
<category: 'actions'>
| ctx |
ctx := [anError signalerContext shortStack ] on: Error
d o : [: ex | ex return: '' ].
^ ctx
]
SoPortableUtil class >> substringsFrom: aString [
"ToDo: Support other Smalltalks"
"##Squeak specific##"
<category: 'actions'>
aString isNil ifTrue: [^ #( ) ].
^ aString substrings
]
]
2011-02-20 17:35:00 +00:00
XML . XMLParser subclass: SoXMLParser [
| namespaces |
findNamespace: ns [
[^ super findNamespace: ns ]
on: XML .InvalidSignal
d o : [^ self customNamespaces at: ns ifAbsentPut: ['unknown' ] ]
]
customNamespaces [
^ namespaces ifNil: [namespaces := Dictionary new ]
]
]
2011-02-18 11:31:26 +00:00
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
d o : [: 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
i f T r u e : [aParsedXMLElement characterData ]
i f F a l s e : [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
r e j e c t : [: 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'>
2011-02-20 17:35:00 +00:00
^ (SoXMLParser processDocumentString: xmlString
2011-02-18 11:31:26 +00:00
b e f o r e S c a n D o : [: p | p validate: false ]) root
]
]
Object subclass: SoXmlAttributesHolder [
| namespaceDict otherDict |
<category: 'SoXML-Base'>
< c o m m e n t : '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
i f T r u e : [self namespaceDict at: SoXmlConstants xmlnsPrefix , prefix put: uri ]
i f F a l s e :
[self namespaceDict at: SoXmlConstants xmlnsPrefixColon , prefix put: uri ]
]
declaredNamespacePrefixes [
<category: 'actions'>
^ self namespaceDict keys collect:
[: each |
each = SoXmlConstants xmlnsPrefix
i f T r u e : ['' ]
i f F a l s e :
[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
i f A b s e n t : [self namespaceDict at: SoXmlConstants xmlnsPrefix ifAbsent: aBlock ]
]
getAttributeLike: aNameString [
<category: 'actions'>
| key |
key := self otherDict keys detect: [: each | aNameString match: each ]
i f N o n e : [].
key isNil
i f T r u e :
[key := self namespaceDict keys detect: [: each | aNameString match: each ]
i f N o n e : []].
^ self getAttributeNamed: key
]
getAttributeNamed: aNameString [
<category: 'actions'>
^ self otherDict at: aNameString
i f A b s e n t : [self namespaceDict at: aNameString ifAbsent: []]
]
hasAttributeLike: aNameString [
<category: 'actions'>
^ (self otherDict keys detect: [: each | aNameString match: each ]
i f N o n e : [nil ]) notNil
o r :
[(self namespaceDict keys detect: [: each | aNameString match: each ]
i f N o n e : [nil ]) notNil ]
]
hasAttributeNamed: aNameString [
<category: 'actions'>
^ (self otherDict includesKey: aNameString )
o r : [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 )
o r : [attribName = SoXmlConstants xmlnsPrefix ])
i f T r u e : [self namespaceDict at: attribName put: attribValue ]
i f F a l s e : [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'>
< c o m m e n t : '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
n e x t P u t A l l : '<?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
d o : [: each | convertCharDict at: each put: '&#' , each asString , ';' ].
convertCharDict
a t : $& asciiValue put: '&' ;
a t : $< asciiValue put: '<' ;
a t : $> asciiValue put: '>' ;
a t : $' asciiValue put: ''' ;
a t : $" asciiValue put: '"' .
convertCharDict
removeKey: Character space asciiValue ;
removeKey: Character tab asciiValue ;
removeKey: Character cr asciiValue ;
removeKey: Character lf asciiValue .
convertCharDict
r e m o v e K e y : $/ asciiValue ;
r e m o v e K e y : $- asciiValue ;
r e m o v e K e y : $# asciiValue ;
r e m o v e K e y : $. asciiValue
]
SoXmlUtil class >> initParserAdapter [
"Currently YAXO and VWXML conscious"
<category: 'private-initialize'>
2011-02-18 23:03:16 +00:00
parserAdapter := self environment at: #SoVWXMLParserAdapter
2011-02-18 11:31:26 +00:00
i f A b s e n t :
2011-02-18 23:03:16 +00:00
[self environment at: #SoYaxXMLParserAdapter
2011-02-18 11:31:26 +00:00
i f A b s e n t :
[Transcript
cr ;
s h o w : '##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
i f T r u e :
[prefixName := '' .
localName := aString ]
i f F a l s e :
[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
i f T r u e :
[aWriteStream
n e x t P u t A l l : '&#' ;
nextPutAll: charCode asString ;
n e x t P u t : $; ]
i f F a l s e : [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
i f T r u e :
[self
writeUnicodeChar: eachChar
code: val
on: wStr ]
i f F a l s e :
[| conv |
conv := cDict at: val ifAbsent: [].
conv isNil
i f T r u e : [wStr nextPut: eachChar ]
i f F a l s e : [wStr nextPutAll: conv ]]].
^ wStr
]
]
Object subclass: SoXmlWrapElement [
| prefixName localName name value attributesHolder children parent isEmptyBody isPrintCDATA |
<category: 'SoXML-Base'>
< c o m m e n t : '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
i f N o t E m p t y D o : [: prefixes | prefixes ]
i f E m p t y : [self parent ifNotNilDo: [: par | par declaredNamespacePrefixes ]]
]
allDeclaredNamespaceURIFor: prefix [
<category: 'actions'>
^ self attributesHolder declaredNamespaceURIFor: prefix
i f A b s e n t :
[self parent notNil ifTrue: [self parent declaredNamespaceURIFor: prefix ]]
]
attributesDictionary [
<category: 'actions'>
^ self attributesHolder asDictionary
]
attributesHolder [
<category: 'accessing'>
attributesHolder isNil
i f T r u e : [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 )
d o : [: each | self initChildElementByDom: each ]
]
initChildElementByDom: aParsedXmlElement [
<category: 'private-init'>
| parentElem childElmClass child |
(SoXmlUtil isTextElement: aParsedXmlElement )
i f T r u e : [^ 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
i f F a l s e :
[self value isNil ifFalse: [self privPrintXmlContentOn: aStream ].
children isNil
i f F a l s e :
["ugly - but for performance"
2011-02-18 23:03:16 +00:00
aStream nl .
2011-02-18 11:31:26 +00:00
self privPrintChildrenOn: aStream indent: level + 1 .
level timesRepeat: [aStream space ]]]
]
printXmlFooterOn: aStream [
<category: 'printing'>
self isXmlPrintable ifFalse: [^ self ].
self isEmptyBody
i f F a l s e :
[aStream nextPut: $< .
aStream nextPut: $/ .
self writeName: self name on: aStream .
aStream nextPut: $> ]
]
printXmlHeaderOn: aStream [
<category: 'printing'>
self isXmlPrintable ifFalse: [^ self ].
self isEmptyBody
i f T r u e :
[aStream nextPut: $< .
self writeName: self name on: aStream .
self privPrintAttribsOn: aStream .
aStream nextPut: $/ .
aStream nextPut: $> ]
i f F a l s e :
[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 .
2011-02-18 23:03:16 +00:00
aStream nl
2011-02-18 11:31:26 +00:00
]
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 )
d o : [: each | each printXmlOn: aStream indent: level ]
]
privPrintXmlContentOn: aStream [
<category: 'private'>
self isPrintCDATA
i f T r u e :
[aStream nextPutAll: '<![CDATA[' .
aStream nextPutAll: self value .
aStream nextPutAll: ']]>' ]
i f F a l s e : [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
r e j e c t : [: 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
]