<?xml version="1.0"?>

<st-source>
<!-- 
Name: XSL
Notice: Copyright © 2008 Cincom Systems, Inc.  All Rights Reserved.
Comment: XSL provides support code necessary to apply an XSL stylesheet to an XML file in order to transform it into another representation. Most XSL transformation elements are supported, and are implemented as subclasses of XSLCommand.

Further information on XSL support can be found in the "Application Developer's Guide" (located in the /doc subdirectory of the VisualWorks installation).
DbIdentifier: bear73
DbTrace: 32998
DevelopmentPrerequisites: #(#(#any 'XPath' ''))
PackageName: XSL
Parcel: #('XSL')
ParcelName: XSL
PrerequisiteParcels: #(#('XPath' ''))
PrintStringCache: (7.1 - 1.0,bobw)
Version: 7.6
Date: 12:28:21 pm February 1, 2008
 -->
<time-stamp>From VisualWorks®, 7.6 of February 1, 2008 on February 1, 2008 at 12:28:21 pm</time-stamp>


<do-it>(Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned.  Choose terminate or close.']</do-it>

<name-space>
<name>XSL</name>
<environment>Smalltalk</environment>
<private>false</private>
<imports>
			private XML.Text
			private drillDown Smalltalk.XML.*
			private Smalltalk.*
			</imports>
<category>XMLParsing</category>
<attributes>
<package>XSL</package>
</attributes>
</name-space>

<class>
<name>XSLNodeBuilder</name>
<environment>XSL</environment>
<super>XML.NodeBuilder</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>nodeNameMap </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Support</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>XSLCommand</name>
<environment>XSL</environment>
<super>XML.Element</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CountingCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>format prefix postfix lang letterValue digitGroupSep digitsPerGroup sequenceSrc </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Counting</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CounterCommand</name>
<environment>XSL</environment>
<super>XSL.CountingCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Counting</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>XSL_PI</name>
<environment>XSL</environment>
<super>XML.PI</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>block </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Control</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>Template</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>hasStripped </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CounterScopeCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Counting</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CountersCommand</name>
<environment>XSL</environment>
<super>XSL.CountingCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Counting</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>GeneralCountingProxy</name>
<environment>XSL</environment>
<super>Core.Link</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>counters </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Support</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ElementProxy</name>
<environment>XSL</environment>
<super>XSL.GeneralCountingProxy</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>contents attributes </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Support</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>Rank</name>
<environment>XSL</environment>
<super>Core.Array</super>
<private>false</private>
<indexed-type>objects</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Support</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>IfCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>testPattern </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Control</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CallTemplateCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Control</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>RuleSet</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Top Level</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>XSLDefinition</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>importance </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>Rule</name>
<environment>XSL</environment>
<super>XSL.XSLDefinition</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>pattern name specific priority mode variables </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Top Level</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CounterIncrementCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name amount </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Counting</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ElementCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name useAttrs </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>NodeIterator</name>
<environment>XSL</environment>
<super>Core.Object</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>stack current </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Support</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>DenormalizedText</name>
<environment>XSL</environment>
<super>XML.Text</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ValueOfCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>expression </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>AttributeCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CopyCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>useAttrs </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>TextTemplate</name>
<environment>XSL</environment>
<super>XML.Text</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>hasStripped </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CommentCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>RuleDatabase</name>
<environment>XSL</environment>
<super>Core.Object</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>rules variables normalized namedTemplates attributeSets currentImportance uriStack output </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Support</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>TextCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ChooseOtherwiseCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Control</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>XSLNodeContext</name>
<environment>XSL</environment>
<super>XML.XPathNodeContext</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>db mode </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-XSL</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>NumberFormat</name>
<environment>XSL</environment>
<super>Core.Link</super>
<private>false</private>
<indexed-type>objects</indexed-type>
<inst-vars>format separator </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Support</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ForEachCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>selectPattern sortList variables </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Control</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CopyOfCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>expression </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>VariableDefinition</name>
<environment>XSL</environment>
<super>XSL.XSLDefinition</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name expression </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ChooseWhenCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>testPattern </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Control</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CounterResetCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Counting</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>OutputCommand</name>
<environment>XSL</environment>
<super>XSL.XSLDefinition</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>method version encoding omitXmlDeclaration standalone doctypePublic doctypeSystem cdataSectionElements indent mediaType </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ApplyTemplatesCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>selectPattern sortList mode </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Control</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>SAXTextWriter</name>
<environment>XSL</environment>
<super>XML.SAXWriter</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Output</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>Import</name>
<environment>XSL</environment>
<super>XSL.XSLDefinition</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>href </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Top Level</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ParamDefinition</name>
<environment>XSL</environment>
<super>XSL.XSLDefinition</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name expression </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>SortCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>selectPattern order lang dataType caseOrder </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Control</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ChooseCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Control</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>Include</name>
<environment>XSL</environment>
<super>XSL.XSLDefinition</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>href </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Top Level</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>WithParamCommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name expression </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>ChainedDictionary</name>
<environment>XSL</environment>
<super>Core.Dictionary</super>
<private>false</private>
<indexed-type>objects</indexed-type>
<inst-vars>parent </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Top Level</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>AttributeSet</name>
<environment>XSL</environment>
<super>XSL.XSLDefinition</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name useAttrs </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Top Level</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>CountingProxy</name>
<environment>XSL</environment>
<super>XSL.GeneralCountingProxy</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Support</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>SAXHtmlWriter</name>
<environment>XSL</environment>
<super>XML.SAXWriter</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>htmlSpecialEmptyTags </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Output</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>NumberCommand</name>
<environment>XSL</environment>
<super>XSL.CountingCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>level count from </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes-Counting</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>PICommand</name>
<environment>XSL</environment>
<super>XSL.XSLCommand</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<class>
<name>DecimalFormat</name>
<environment>XSL</environment>
<super>XSL.XSLDefinition</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XSL-Nodes</category>
<attributes>
<package>XSL</package>
</attributes>
</class>

<shared-variable>
<name>XSL_URI</name>
<environment>XSL</environment>
<private>false</private>
<constant>false</constant>
<category>XSL-Support</category>
<initializer> 'http://www.w3.org/1999/XSL/Transform' </initializer>
<attributes>
<package>XSL</package>
</attributes>
</shared-variable>

<shared-variable>
<name>XPathExtensionFunctions</name>
<environment>XSL.XSLCommand</environment>
<private>false</private>
<constant>false</constant>
<category>xpath</category>
<attributes>
<package>XSL</package>
</attributes>
</shared-variable>

<methods>
<class-id>XSL.XSLNodeBuilder</class-id> <category>building</category>

<body package="XSL" selector="makeText:">makeText: text

	^TextTemplate text: text</body>

<body package="XSL" selector="pi:text:">pi: nm text: text

	^XSL_PI new name: nm text: text</body>

<body package="XSL" selector="tag:attributes:elements:position:stream:">tag: tag attributes: attributes elements: elements position: p stream: stream

	| elementClass |
	elementClass := tag namespace = XSL_URI
		ifTrue: [self nodeNameMap
					at: tag type
					ifAbsent: [self error: 'The action ', tag asString, ' is not yet implemented']]
		ifFalse: [Template].
	^elementClass tag: tag attributes: attributes elements: elements</body>
</methods>

<methods>
<class-id>XSL.XSLNodeBuilder</class-id> <category>private</category>

<body package="XSL" selector="nodeNameMap">nodeNameMap

	nodeNameMap == nil
		ifTrue:
			[nodeNameMap := Dictionary new.
			XSLCommand withAllSubclasses do: [:beh |
				beh tag == nil ifFalse: [nodeNameMap at: beh tag put: beh]]].
	^nodeNameMap</body>
</methods>

<methods>
<class-id>XSL.XSLCommand</class-id> <category>private</category>

<body package="XSL" selector="checkQNameSyntax:">checkQNameSyntax: aString

	| str mode colons ch valid |
	str := aString readStream.
	mode := #colon.
	colons := 0.
	[str atEnd] whileFalse:
		[ch := str next.
		mode == #colon
			ifTrue:
				[valid := ch = $_ or: [ch isLetter].
				mode := #letter]
			ifFalse: [ch = $:
				ifTrue:
					[valid := true.
					colons := colons+1.
					mode := #colon]
				ifFalse:
					[valid := ch isLetter or: [ch isDigit or: ['.-_' includes: ch]].
					mode := #letterOrDigit]].
		valid ifFalse: [self error: 'Syntax error in qualified name.']].
	(mode = #colon or: [colons &gt; 1])
		ifTrue: [self error: 'Syntax error in qualified name.'].</body>

<body package="XSL" selector="checkURISyntax:">checkURISyntax: aString

	| n type ch |
	n := aString findLast: [:c | c = $#].
	n = aString size
		ifTrue: [self error: 'The name for an attribute or element, using the x#y syntax, has no type following the #.'].
	type := aString copyFrom: n+1 to: aString size.
	ch := type at: 1.
	(ch = $_ or: [ch isLetter])
		ifFalse: [self error: ('Type name syntax error in "&lt;1s&gt;".' expandMacrosWith: type)].
	2 to: type size do: [:i |
		ch := type at: i.
		(ch isLetter or: [ch isDigit or: ['.-_' includes: ch]])
			ifFalse: [self error: ('Type name syntax error in "&lt;1s&gt;".' expandMacrosWith: type)]]</body>

<body package="XSL" selector="collate:to:within:">collate: node1 to: node2 within: aNodeContext

	| list sign |
	(list := self sortList) == nil
		ifFalse:
			[1 to: list size do: [:i |
				sign := (list at: i) collate: node1 to: node2 within: aNodeContext.
				sign = 0 ifFalse: [^sign = -1]]].
	^node1 precedes: node2</body>

<body package="XSL" selector="readAttribute:">readAttribute: attName

	^self readAttribute: attName
		default: [self error: ('&lt;1s&gt; needs to have an attribute named &lt;2s&gt;'
					expandMacrosWith: self tag asString
					with: attName)]</body>

<body package="XSL" selector="readAttribute:default:">readAttribute: attName default: def

	| att |
	att := self valueOfAttribute: attName ifAbsent: [nil].
	^att == nil
		ifTrue: [def value]
		ifFalse: [att]</body>

<body package="XSL" selector="readInteger:default:">readInteger: attName default: def

	| att val |
	att := self valueOfAttribute: attName ifAbsent: [nil].
	^att == nil
		ifTrue: [def value]
		ifFalse:
			[att isEmpty ifTrue: [self error: ('The &lt;1s&gt; attribute is empty' expandMacrosWith: attName)].
			att := att readStream.
			val := Number readFrom: att.
			val = 0 ifTrue: [self error: 'Bad number format, ', (att instVarAt: 1)].
			att atEnd ifFalse: [self error: ('The &lt;1s&gt; attribute is not a legal integer value' expandMacrosWith: attName)].
			val]</body>

<body package="XSL" selector="readMatchPattern:">readMatchPattern: attName

	^self readMatchPattern: attName
		default: [self error: ('&lt;1s&gt; needs to have an attribute named &lt;2s&gt;'
					expandMacrosWith: self tag asString
					with: attName)]</body>

<body package="XSL" selector="readMatchPattern:default:">readMatchPattern: attName default: def

	| att |
	att := self valueOfAttribute: attName ifAbsent: [nil].
	^att == nil
		ifTrue: [def value]
		ifFalse: [XPathParser new xmlNode: self;
								functions: self class xslFunctions;
								parse: att as: #expression]</body>

<body package="XSL" selector="readSelectPattern:">readSelectPattern: attName

	^self readSelectPattern: attName
		default: [self error: ('&lt;1s&gt; needs to have an attribute named &lt;2s&gt;'
					expandMacrosWith: self tag asString
					with: attName)]</body>

<body package="XSL" selector="readSelectPattern:default:">readSelectPattern: attName default: def

	| att d |
	att := self valueOfAttribute: attName ifAbsent: [nil].
	^att == nil
		ifTrue:
			[d := def value.
			d == nil ifFalse: [d := XPathParser new xmlNode: self;
								functions: self class xslFunctions;
								parse: d as: #expression].
			d]
		ifFalse: [XPathParser new xmlNode: self;
								functions: self class xslFunctions;
								parse: att as: #expression]</body>

<body package="XSL" selector="readTag:">readTag: attName

	| att |
	att := self valueOfAttribute: attName ifAbsent: [nil].
	^att == nil
		ifTrue: [self error: ('&lt;1s&gt; needs to have an attribute named &lt;2s&gt;'
					expandMacrosWith: self tag asString
					with: attName)]
		ifFalse: [att]</body>

<body package="XSL" selector="readTagList:default:">readTagList: attName default: defaultBlock

	| att str output buffer ch |
	att := self valueOfAttribute: attName ifAbsent: [nil].
	^att == nil
		ifTrue: [defaultBlock value]
		ifFalse:
			[str := att readStream.
			output := OrderedCollection new.
			buffer := String new writeStream.
			[str skipSeparators; atEnd]
				whileFalse:
					[[(ch := str next) notNil and: [ch isSeparator not]]
						whileTrue: [buffer nextPut: ch].
					output add: buffer contents.
					buffer reset].
			output asArray]</body>

<body package="XSL" selector="xslNodesFrom:">xslNodesFrom: aNodeContext

	| list nc |
	list := aNodeContext node
		selectNodes: [:nd | nd isAttribute not or: [nd tag qualifier ~= 'xmlns']].
	nc := aNodeContext copy documentOrder.
	nc addAll: list.
	^nc</body>
</methods>

<methods>
<class-id>XSL.XSLCommand</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	self shouldNotImplement</body>
</methods>

<methods>
<class-id>XSL.XSLCommand</class-id> <category>accessing</category>

<body package="XSL" selector="defaultTag">defaultTag

	^'xsl:', self class tag</body>

<body package="XSL" selector="defineVariable:">defineVariable: aVariable

	self parent defineVariable: aVariable</body>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	self subclassResponsibility</body>

<body package="XSL" selector="sortList">sortList
	"Answer a list of sort blocks that take two arguments,
	and return -1 if the arguments are in order, 1 if they
	are in reversed order, and 0 if that particular sort block
	cannot order them."

	^nil</body>

<body package="XSL" selector="xslElements">xslElements

	^self children select: [:i | i isContent]</body>
</methods>

<methods>
<class-id>XSL.XSLCommand</class-id> <category>testing</category>

<body package="XSL" selector="generatesAttributes">generatesAttributes

	^false</body>

<body package="XSL" selector="isStylesheetEntry">isStylesheetEntry

	Transcript cr; tab; show: ('Stylesheet contains a top-level element that is not permitted (&lt;1s&gt;)'
			expandMacrosWith: self tag).
	Transcript cr; tab; show: 'It has been ignored'.
	^false</body>

<body package="XSL" selector="shouldStrip">shouldStrip

	^true</body>
</methods>

<methods>
<class-id>XSL.XSLCommand</class-id> <category>initialize</category>

<body package="XSL" selector="initialize">initialize

	super initialize.
	elements := #().
	userData := false</body>

<body package="XSL" selector="normalize">normalize

	self stripSpace.
	self xslElements do: [:elm | elm normalize].</body>

<body package="XSL" selector="stripSpace">stripSpace

	self shouldStrip
		ifTrue: [self elements: (self children select: [:t | t isBlankText not])].</body>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData := true.</body>
</methods>

<methods>
<class-id>XSL.XSLCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	self subclassResponsibility</body>

<body package="XSL" selector="process:into:takeArgumentsFrom:">process: aNodeContext into: aProxy takeArgumentsFrom: arguments

	self process: aNodeContext into: aProxy</body>

<body package="XSL" selector="processAttributeSets:into:">processAttributeSets: aNodeContext into: aProxy

	| list vars |
	self useAttrs isEmpty ifTrue: [^self].
	vars := aNodeContext variables.
	aNodeContext variables: vars parent.
	self useAttrs do: [:attSetName |
		list := aNodeContext db attributesForSet: attSetName.
		list do: [:att | att process: aNodeContext into: aProxy]].
	aNodeContext variables: vars.</body>

<body package="XSL" selector="processAttributeValue:for:">processAttributeValue: aString for: aNodeContext

	| source ch output elm p expr |
	source := XPathReadStream on: aString.
	output := (String new: 64) writeStream.
	[source atEnd]
		whileFalse:
			[ch := source next.
			ch = ${
				ifTrue:
					[(source peekFor: ${)
						ifTrue: [output nextPut: ${]
						ifFalse:
							[p := XPathParser new.
							p initScanner;
								xmlNode: self;
								functions: self class xslFunctions;
								init: source notifying: nil failBlock: nil.
							p expression.
							p atEndOfExpression ifFalse: [self error: 'Syntax error in: ', aString storeString].
							expr := p result.
							elm := expr xpathValueIn: aNodeContext.
							output nextPutAll: elm xpathAsString.
							p pastEnd ifFalse: [source skip: -1]]]
				ifFalse: [ch = $}
					ifTrue:
						[source next = $} ifFalse: [self error: 'Expected doubled }'].
						output nextPut: $}]
					ifFalse: [output nextPut: ch]]].
	^output contents</body>

<body package="XSL" selector="resolveComputedTag:">resolveComputedTag: nm

	| n type ns qualifier |
	^(nm includes: $#)
		ifTrue:
			[self checkURISyntax: nm.
			n := nm findLast: [:c | c = $#].
			type := nm copyFrom: n+1 to: nm size.
			ns := nm copyFrom: 1 to: n-1.
			qualifier := self findQualifierAtNamespace: 'quote:', ns.
			qualifier == nil
				ifTrue: [qualifier := self findQualifierAtNamespace: ns].
			qualifier == nil ifTrue: [self error: ('The namespace &lt;1s&gt; has not been bound to a qualifier in this stylesheet, and automatic creation of qualifiers has not been implemented.' expandMacrosWith: ns)].
			NodeTag new qualifier: qualifier ns: ns type: type]
		ifFalse:
			[self checkQNameSyntax: nm.
			self resolveTag: nm].</body>

<body package="XSL" selector="resolveTag:">resolveTag: aTagString

	| c qual ns |
	c := aTagString occurrencesOf: $:.
	^c = 0
		ifTrue: [NodeTag new qualifier: '' ns: '' type: aTagString]
		ifFalse: [c &gt; 1
			ifTrue: [self error: 'A qualified name has too many colons.']
			ifFalse:
				[c := aTagString indexOf: $:.
				(c = 1 or: [c = aTagString size])
					ifTrue: [self error: 'A qualified name cannot begin or end with a colon.'].
				qual := aTagString copyFrom: 1 to: c-1.
				ns := self findNamespaceAt: qual.
				ns == nil ifTrue: [self error: ('The namespace qualifier &lt;1s&gt; has not been bound to a namespace in this stylesheet' expandMacrosWith: qual)].
				"Use a # in the match to make sure there's at least one more character"
				('quote:#*' match: ns)
					ifTrue: [ns := ns copyFrom: 'quote:' size+1 to: ns size].
				NodeTag new qualifier: qual ns: ns type: (aTagString copyFrom: c+1 to: aTagString size)]]</body>

<body package="XSL" selector="selectAll:withPattern:">selectAll: startNode withPattern: pattern

	^pattern xpathValueIn: startNode</body>

<body package="XSL" selector="valueAsVariableIn:">valueAsVariableIn: aNodeContext

	| new list |
	^self expression == nil
		ifTrue:
			[new := ElementProxy new.
			list := self xslElements.
			1 to: list size do: [:i || elm |
				elm := list at: i.
				elm process: aNodeContext into: new].
			new]
		ifFalse: [self expression xpathValueIn: aNodeContext]</body>
</methods>

<methods>
<class-id>XSL.XSLCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^nil</body>

<body package="XSL" selector="xslFunctions">xslFunctions

	^XPathExtensionFunctions</body>
</methods>

<methods>
<class-id>XSL.XSLCommand class</class-id> <category>xpath</category>

<body package="XSL" selector="formatNumber:pattern:formatName:in:">formatNumber: aNumber pattern: pattern formatName: formatName in: aNodeContext

	^aNumber xpathAsString</body>
</methods>

<methods>
<class-id>XSL.XSLCommand class</class-id> <category>class initialization</category>

<body package="XSL" selector="initialize">initialize
	"XSLCommand initialize"

	| functions |
	functions := ChainedDictionary new.
	functions parent: XPathFunction baseFunctions.
	functions at: 'format-number' put: (XPathFunction new
			name: 'format-number';
			valueBlock: [:fn :ns || n s1 s2 |
					(fn arguments size between: 2 and: 3)
						ifFalse: [self error: 'format-number() takes two or three arguments.'].
					n := ((fn arguments at: 1) xpathEvalIn: ns) xpathAsNumber.
					s1 := ((fn arguments at: 2) xpathEvalIn: ns) xpathAsString.
					fn arguments size = 3
						ifTrue: [s2 := ((fn arguments at: 3) xpathEvalIn: ns) xpathAsString]
						ifFalse: [s2 := nil].
					self formatNumber: n pattern: s1 formatName: s2 in: ns]).
	XPathExtensionFunctions := functions.</body>
</methods>

<methods>
<class-id>XSL.CountingCommand</class-id> <category>accessing</category>

<body package="XSL" selector="digitGroupSep">digitGroupSep

	self testPatternInitialized.
	^digitGroupSep</body>

<body package="XSL" selector="digitsPerGroup">digitsPerGroup

	self testPatternInitialized.
	^digitsPerGroup</body>

<body package="XSL" selector="format">format

	self testPatternInitialized.
	^format</body>

<body package="XSL" selector="lang">lang

	self testPatternInitialized.
	^lang</body>

<body package="XSL" selector="letterValue">letterValue

	self testPatternInitialized.
	^letterValue</body>

<body package="XSL" selector="sequenceSrc">sequenceSrc

	self testPatternInitialized.
	^sequenceSrc</body>
</methods>

<methods>
<class-id>XSL.CountingCommand</class-id> <category>private</category>

<body package="XSL" selector="format:by:">format: number by: aFormat

	| n s |
	aFormat size = 1
		ifFalse: [self error: ('Unrecognized number format = "&lt;1s&gt;"' expandMacrosWith: aFormat)].
	aFormat = 'a'
		ifTrue:
			[n := self radix: number base: 26.
			s := n collect: [:i | (i + $a asInteger) asCharacter].
			^String withAll: s].
	aFormat = 'A'
		ifTrue:
			[n := self radix: number base: 26.
			s := n collect: [:i | (i + $A asInteger) asCharacter].
			^String withAll: s].
	aFormat = 'i'
		ifTrue:
			[^self romanNumeral: number].
	aFormat = 'I'
		ifTrue:
			[^(self romanNumeral: number) asUppercase].
	aFormat = '1'
		ifTrue:
			[^number printString].
	self error: 'Unrecognized format'</body>

<body package="XSL" selector="radix:base:">radix: number base: b

	| out n |
	n := number-1.
	n &lt; b ifTrue: [^Array with: n].
	out := OrderedCollection new.
	n := number.
	[n &lt; b]
		whileFalse:
			[out addFirst: n\\b.
			n := n//b].
	out addFirst: n-1.
	^out</body>

<body package="XSL" selector="romanNumeral:">romanNumeral: number

	| n cycle output idx letters digit |
	n := number.
	cycle := #('ivx' 'xlc' 'cdm').
	output := OrderedCollection new.
	idx := 0.
	[n = 0]
		whileFalse:
			[letters := cycle at: (idx := idx+1).
			digit := n\\10.
			digit := #(#() #(1) #(1 1) #(1 1 1) #(1 2) #(2) #(2 1) #(2 1 1) #(2 1 1 1) #(1 3))
					at: digit+1.
			output addAllFirst: (digit collect: [:i | letters at: i]).
			n := n//10].
	^String withAll: output</body>

<body package="XSL" selector="tokenizeFormat:">tokenizeFormat: aString

	| str isFormat tok tokens t resultFormat |
	str := aString readStream.
	tokens := OrderedCollection new.
	isFormat := [:ch | ch isDigit or: [ch isLetter]].
	[str atEnd] whileFalse:
		[tok := ''.
		(isFormat value: str peek)
			ifTrue: [[str atEnd or: [(isFormat value: str peek) not]]
				whileFalse: [tok := tok copyWith: str next]]
			ifFalse: [[str atEnd or: [isFormat value: str peek]]
				whileFalse: [tok := tok copyWith: str next]].
		tokens add: tok].
	(tokens isEmpty or: [isFormat value: tokens first first])
		ifFalse: [prefix := tokens removeFirst].
	(tokens isEmpty or: [isFormat value: tokens last first])
		ifFalse: [postfix := tokens removeLast].
	tokens size = 0
		ifTrue: [resultFormat := nil]
		ifFalse: [tokens size = 1
			ifTrue:
				[resultFormat := NumberFormat new format: tokens first; separator: '.'.
				resultFormat nextLink: resultFormat]
			ifFalse:
				[t := (1 to: tokens size by: 2) collect:
					[:i | NumberFormat new
							format: (tokens at: i);
							separator: (tokens at: (i+1 min: tokens size-1))].
				1 to: t size do: [:i | (t at: i) nextLink: (t at: (i+1 min: t size))].
				resultFormat := t first]].
	^resultFormat</body>
</methods>

<methods>
<class-id>XSL.CountingCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	format := self readAttribute: 'format' default: ['1'].
	lang := self readAttribute: 'xml:lang' default: [nil].
	letterValue := self readAttribute: 'letter-value' default: [nil].
	digitGroupSep := self readAttribute: 'digit-group-sep' default: [nil].
	digitsPerGroup := self readInteger: 'n-digits-per-group' default: [3].
	sequenceSrc := self readAttribute: 'sequence-src' default: [nil].</body>
</methods>

<methods>
<class-id>XSL.CountingCommand</class-id> <category>processing</category>

<body package="XSL" selector="format:for:">format: countList for: aNodeContext

	| str fmt |
	str := String new writeStream.
	fmt := self processAttributeValue: self format for: aNodeContext.
	fmt := self tokenizeFormat: fmt.
	prefix == nil ifFalse: [str nextPutAll: prefix].
	1 to: countList size do: [:i |
		str nextPutAll: (self format: (countList at: i) by: fmt format).
		i = countList size ifFalse: [str nextPutAll: fmt separator].
		fmt := fmt nextLink].
	postfix == nil ifFalse: [str nextPutAll: postfix].
	^str contents</body>
</methods>

<methods>
<class-id>XSL.CounterCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	super testPatternInitialized.
	name := self readAttribute: 'name'.
	userData := true.</body>
</methods>

<methods>
<class-id>XSL.CounterCommand</class-id> <category>accessing</category>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>
</methods>

<methods>
<class-id>XSL.CounterCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| c |
	c := aProxy counterNamed: self name.
	c == nil
		ifFalse:
			[aProxy add: (Text new text: (self format: (Array with: c value) for: aNodeContext))].</body>
</methods>

<methods>
<class-id>XSL.CounterCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'counter'</body>
</methods>

<methods>
<class-id>XSL.XSL_PI</class-id> <category>accessing</category>

<body package="XSL" selector="stripSpace">stripSpace

	^self</body>
</methods>

<methods>
<class-id>XSL.XSL_PI</class-id> <category>testing</category>

<body package="XSL" selector="isContent">isContent

	^name = 'vwst_xsl'</body>

<body package="XSL" selector="isStylesheetEntry">isStylesheetEntry

	^name = 'vwst_xsl'</body>
</methods>

<methods>
<class-id>XSL.XSL_PI</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	block == nil
		ifTrue: [block := Compiler evaluate: text].
	(block class == BlockClosure and: [block numArgs = 1])
		ifFalse: [self error: '"', text, '" is not a legal Smalltalk processing instruction'].
	aProxy addAll: (block value: aNodeContext)</body>
</methods>

<methods>
<class-id>XSL.XSL_PI</class-id> <category>initialize</category>

<body package="XSL" selector="normalize">normalize

	^self</body>
</methods>

<methods>
<class-id>XSL.Template</class-id> <category>accessing</category>

<body package="XSL" selector="importanceHolder:">importanceHolder: dummy</body>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	^self</body>
</methods>

<methods>
<class-id>XSL.Template</class-id> <category>testing</category>

<body package="XSL" selector="importance">importance
	"Really only needs to be &gt; 0 to beat the builtin rule that matches
	against the root of the document, but we throw in a bit of paranoia."

	^1000</body>

<body package="XSL" selector="match:">match: aNodeContext

	^aNodeContext node isDocument</body>

<body package="XSL" selector="modeIsLike:">modeIsLike: aMode

	^aMode isNil</body>
</methods>

<methods>
<class-id>XSL.Template</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| oc list |
	oc := aProxy childProxy.
	oc attributes: (self processAttributes: self attributes for: aNodeContext).
	list := self xslElements.
	1 to: list size do: [:i || elm |
		elm := list at: i.
		elm process: aNodeContext into: oc].
	aProxy addNode: (Element tag: tag attributes: oc attributes elements: oc children)</body>

<body package="XSL" selector="process:into:arguments:">process: aNodeContext into: aProxy arguments: arguments
	"The arguments are ignored because, if I am being used
	as a top-level stylesheet, there's no place to declare the
	top-level &lt;xsl:param&gt; definitions."

	self process: aNodeContext into: aProxy</body>

<body package="XSL" selector="processAttributes:for:">processAttributes: attList for: aNodeContext

	| newList substitution newAtt |
	newList := OrderedCollection new.
	attList do: [:att |
		(att tag namespace = XSL_URI)
			ifTrue:
				[newAtt := self processXSLAttribute: att for: aNodeContext.
				newAtt == nil ifFalse: [newList add: newAtt]]].
	attList do: [:att |
		(att tag namespace = XSL_URI)
			ifFalse:
				[substitution := self processAttributeValue: att value for: aNodeContext.
				newAtt := Attribute name: att key value: substitution.
				newList add: newAtt]].
	^newList isEmpty
		ifTrue: [nil]
		ifFalse: [newList asArray]</body>

<body package="XSL" selector="processXSLAttribute:for:">processXSLAttribute: att for: aNodeContext

	att tag type = 'version'
		ifTrue:
			[" aNodeContext db version: att value. "
			^nil].
	att tag type = 'use-attribute-set'
		ifTrue:
			[^self notYetImplementedError].
	^self notYetImplementedError</body>
</methods>

<methods>
<class-id>XSL.Template</class-id> <category>loading</category>

<body package="XSL" selector="topLevelAddToRuleDB:">topLevelAddToRuleDB: aDB
	"This is only understood by a small subset of commands."

	self tag namespace = XSL_URI
		ifTrue: [self error: ('"&lt;1s&gt;" not recognized as an XSL command'
			expandMacrosWith: self tag asString)].
	aDB addRule: self</body>
</methods>

<methods>
<class-id>XSL.CounterScopeCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| tempProxy |
	tempProxy := aProxy countingProxy.
	self xslElements do: [:elm |
		elm process: aNodeContext into: tempProxy].</body>
</methods>

<methods>
<class-id>XSL.CounterScopeCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'counter-scope'</body>
</methods>

<methods>
<class-id>XSL.CountersCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	super testPatternInitialized.
	name := self readAttribute: 'name'.
	userData := true.</body>
</methods>

<methods>
<class-id>XSL.CountersCommand</class-id> <category>accessing</category>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>
</methods>

<methods>
<class-id>XSL.CountersCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| list |
	list := OrderedCollection new.
	aProxy counterValuesNamed: self name into: list.
	aProxy add: (Text new text: (self format: list for: aNodeContext))</body>
</methods>

<methods>
<class-id>XSL.CountersCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'counters'</body>
</methods>

<methods>
<class-id>XSL.GeneralCountingProxy</class-id> <category>accessing</category>

<body package="XSL" selector="childProxy">childProxy

	^ElementProxy new nextLink: self; yourself</body>

<body package="XSL" selector="counterNamed:">counterNamed: nm

	| c |
	counters == nil
		ifTrue: [c := nil]
		ifFalse: [c := counters at: nm ifAbsent: []].
	^c == nil
		ifTrue: [nextLink == nil
			ifTrue: [nil]
			ifFalse: [nextLink counterNamed: nm]]
		ifFalse: [c]</body>

<body package="XSL" selector="counterValuesNamed:into:">counterValuesNamed: nm into: list

	| c |
	self nextLink == nil
		ifFalse: [self nextLink counterValuesNamed: nm into: list].
	counters == nil
		ifTrue: [c := nil]
		ifFalse: [c := counters at: nm ifAbsent: []].
	c == nil
		ifFalse: [list add: c value]</body>

<body package="XSL" selector="countingProxy">countingProxy

	^CountingProxy new nextLink: self; yourself</body>

<body package="XSL" selector="resetCounter:">resetCounter: nm

	counters == nil ifTrue: [counters := Dictionary new].
	counters at: nm put: 0 asValue.
	^counters at: nm</body>

<body package="XSL" selector="root">root

	| n |
	n := self.
	[n nextLink == nil]
		whileFalse: [n := n nextLink].
	^n</body>
</methods>

<methods>
<class-id>XSL.ElementProxy</class-id> <category>building</category>

<body package="XSL" selector="addAttribute:">addAttribute: attribute

	self attributes: (self attributes copyWith: attribute)</body>

<body package="XSL" selector="addNode:">addNode: element

	self children: (self children copyWith: element)</body>
</methods>

<methods>
<class-id>XSL.ElementProxy</class-id> <category>accessing</category>

<body package="XSL" selector="attributes">attributes

	attributes == nil
		ifTrue: [attributes := #()].
	^attributes</body>

<body package="XSL" selector="attributes:">attributes: list

	attributes := list</body>

<body package="XSL" selector="children">children

	contents == nil
		ifTrue: [contents := #()].
	^contents</body>

<body package="XSL" selector="children:">children: list

	contents := list</body>
</methods>

<methods>
<class-id>XSL.ElementProxy</class-id> <category>coercing</category>

<body package="XSL" selector="xpathAsBoolean">xpathAsBoolean

	^self xpathAsString xpathAsBoolean</body>

<body package="XSL" selector="xpathAsNumber">xpathAsNumber

	^self xpathAsString xpathAsNumber</body>

<body package="XSL" selector="xpathAsString">xpathAsString

	| result |
	self children isEmpty ifTrue: [^''].
	self children size = 1 ifTrue: [^self children first xpathStringData].
	result := (String new: 40) writeStream.
	1 to: self children size do: [:i |
		result nextPutAll: (self children at: i) xpathStringData].
	^result contents</body>
</methods>

<methods>
<class-id>XSL.ElementProxy</class-id> <category>enumerating</category>

<body package="XSL" selector="addToXPathHolder:for:">addToXPathHolder: anAssociation for: aNodeContext

	anAssociation value == nil
		ifTrue: [^anAssociation value: self].
	anAssociation value xpathIsNodeSet
		ifTrue: [^self error: 'An XPath expression is answering a combination of Nodes and non-Nodes'].
	self error: 'An XPath expression is answering more than one non-Node value'</body>
</methods>

<methods>
<class-id>XSL.Rank</class-id> <category>comparing</category>

<body package="XSL" selector="rankAgainst:">rankAgainst: aRank
	"Assume two Ranks, of sizes M and N, where M &gt;= N.
	If they have the same elements in the first N elements, the
		shorter Rank has higher priority.
	If there is a difference in the first N elements, assume
		that the first difference occurs at slot S. The Rank
		whose value at S is greater has higher priority."

	| min r ranks |
	ranks := #(#higher #same #lower).
	min := self size min: aRank size.
	1 to: min do: [:i |
		r := ((aRank at: i) - (self at: i)) sign.
		r = 0 ifFalse: [^ranks at: r+2]].
	^ranks at: (self size - aRank size) sign+2</body>
</methods>

<methods>
<class-id>XSL.IfCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	testPattern := self readSelectPattern: 'test'</body>
</methods>

<methods>
<class-id>XSL.IfCommand</class-id> <category>accessing</category>

<body package="XSL" selector="testPattern">testPattern

	self testPatternInitialized.
	^testPattern</body>
</methods>

<methods>
<class-id>XSL.IfCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| list |
	(self testPattern xpathValueIn: aNodeContext) xpathAsBoolean
		ifTrue:
			[list := self xslElements.
			1 to: list size do: [:i || elm |
				elm := list at: i.
				elm process: aNodeContext into: aProxy]]</body>
</methods>

<methods>
<class-id>XSL.IfCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'if'</body>
</methods>

<methods>
<class-id>XSL.CallTemplateCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| rule arguments list vars |
	rule := aNodeContext db ruleNamed: self name.
	arguments := Dictionary new.
	list := self xslElements.
	1 to: list size do: [:i |
		(list at: i) process: aNodeContext intoArgs: arguments].
	rule == nil
		ifTrue: [self error: 'Named template not found']
		ifFalse:
			[vars := aNodeContext variables.
			aNodeContext variables: vars clone.
			rule process: aNodeContext into: aProxy arguments: arguments.
			aNodeContext variables: vars]</body>
</methods>

<methods>
<class-id>XSL.CallTemplateCommand</class-id> <category>accessing</category>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>
</methods>

<methods>
<class-id>XSL.CallTemplateCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	name := self readAttribute: 'name' default: [nil]</body>
</methods>

<methods>
<class-id>XSL.CallTemplateCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'call-template'</body>
</methods>

<methods>
<class-id>XSL.RuleSet</class-id> <category>accessing</category>

<body package="XSL" selector="defineParameter:">defineParameter: aVariable

	^self</body>

<body package="XSL" selector="defineVariable:">defineVariable: aVariable

	^self</body>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	elements := self children select: [:i | i isElement and: [i isStylesheetEntry]].
	elements do: [:i | i purgeUnimportant]</body>
</methods>

<methods>
<class-id>XSL.RuleSet</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	self children do:
		[:elm | elm addToRuleDB: aDB].</body>

<body package="XSL" selector="topLevelAddToRuleDB:">topLevelAddToRuleDB: aDB
	"This is only understood by a small subset of commands."

	self children do:
		[:elm | elm addToRuleDB: aDB].</body>
</methods>

<methods>
<class-id>XSL.RuleSet class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'stylesheet'</body>
</methods>

<methods>
<class-id>XSL.XSLDefinition</class-id> <category>accessing</category>

<body package="XSL" selector="importance">importance

	^importance value</body>

<body package="XSL" selector="importanceHolder:">importanceHolder: aValueHolder

	importance := aValueHolder</body>

<body package="XSL" selector="replaceImportance:with:">replaceImportance: oldValue with: currentImportance

	importance == oldValue
		ifTrue: [importance := currentImportance]</body>
</methods>

<methods>
<class-id>XSL.XSLDefinition</class-id> <category>testing</category>

<body package="XSL" selector="isStylesheetEntry">isStylesheetEntry

	^true</body>
</methods>

<methods>
<class-id>XSL.XSLDefinition</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	self subclassResponsibility</body>
</methods>

<methods>
<class-id>XSL.Rule</class-id> <category>accessing</category>

<body package="XSL" selector="defineParameter:">defineParameter: aVariable

	| old |
	old := variables detect: [:var | var name = aVariable name] ifNone: [].
	(old == nil or: [old == aVariable])
		ifFalse: [self error: 'The parameter "', aVariable name, '" is shadowing another variable in the same template'].
	old == nil ifTrue: [variables add: aVariable].</body>

<body package="XSL" selector="defineVariable:">defineVariable: aVariable

	| old |
	old := variables detect: [:var | var name = aVariable name] ifNone: [].
	(old == nil or: [old == aVariable])
		ifFalse: [self error: 'The variable "', aVariable name, '" is shadowing another variable in the same template'].
	old == nil ifTrue: [variables add: aVariable].</body>

<body package="XSL" selector="mode">mode

	self testPatternInitialized.
	^mode</body>

<body package="XSL" selector="mode:">mode: aMode

	mode := aMode</body>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>

<body package="XSL" selector="pattern">pattern

	self testPatternInitialized.
	^pattern</body>

<body package="XSL" selector="priority">priority

	self testPatternInitialized.
	^priority</body>

<body package="XSL" selector="priority:">priority: aNumber

	priority := aNumber</body>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	^self</body>
</methods>

<methods>
<class-id>XSL.Rule</class-id> <category>testing</category>

<body package="XSL" selector="isStylesheetEntry">isStylesheetEntry

	^true</body>

<body package="XSL" selector="match:">match: aNodeContext

	^self pattern notNil and: [self pattern match: aNodeContext]</body>

<body package="XSL" selector="modeIsLike:">modeIsLike: aMode
	"We can use #any as the 'accept any mode', because
	normal modes are strings. If this is changed, the marker
	for 'any mode' would need to be changed."

	^mode = aMode or: [mode == #any]</body>
</methods>

<methods>
<class-id>XSL.Rule</class-id> <category>initialize</category>

<body package="XSL" selector="computeDefaultPriority:">computeDefaultPriority: expr

	| list |
	^expr class == XPathUnion
		ifTrue:
			[list := Set new.
			expr arguments do: [:expr2 | list add: (self computeDefaultPriority: expr2)].
			list size = 1
				ifTrue: [list asArray first]
				ifFalse: [#notKnown]]
		ifFalse: [((expr class == XPathChildNode or: [expr class == XPathAttributeNode])
					and: [expr child isTerminator and: [expr predicates isEmpty]])
			ifTrue: [expr baseTest class == XPathTaggedNodeTest
				ifTrue: [expr baseTest type == #*
					ifTrue: [expr baseTest namespace == nil ifTrue: [-0.5d] ifFalse: [-0.25d]]
					ifFalse: [0.0d]]
				ifFalse: [('processing-instruction(*)' match: expr printString)
					ifTrue: [self halt]
					ifFalse: [-0.5d]]]
			ifFalse: [0.5]]</body>

<body package="XSL" selector="initialize">initialize

	super initialize.
	priority := 0.
	variables := OrderedCollection new.</body>

<body package="XSL" selector="normalize">normalize

	super normalize.
	(self parent == nil or: [self parent isKindOf: RuleSet])
		ifFalse: [self error: self tag asString, ' can only be used at the top level'].</body>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	name := self readAttribute: 'name' default: [nil].
	pattern := self readMatchPattern: 'match' default: [nil].
	priority := self readInteger: 'priority' default: [self computeDefaultPriority: self pattern].
	mode := self readAttribute: 'mode' default: [nil]</body>
</methods>

<methods>
<class-id>XSL.Rule</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	self pattern == nil ifFalse: [aDB addRule: self].
	self name == nil ifFalse: [aDB addNamedTemplate: self].
	(self pattern == nil and: [self name == nil])
		ifTrue: [self error: 'Templates must have either a name or match attribute or both'].</body>
</methods>

<methods>
<class-id>XSL.Rule</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	self shouldNotImplement</body>

<body package="XSL" selector="process:into:arguments:">process: aNodeContext into: aProxy arguments: arguments

	| list |
	list := self xslElements.
	1 to: list size do: [:i || elm |
		elm := list at: i.
		elm process: aNodeContext into: aProxy takeArgumentsFrom: arguments]</body>
</methods>

<methods>
<class-id>XSL.Rule class</class-id> <category>formatting</category>

<body package="XSL" selector="formatText:">formatText: aNode

	| text tab a |
	a := Attribute new name: 'CLASS' value: 'body'.
	text := aNode characterData.
	tab := String new: 4 withAll: (Character value: 160). "nbsp"
	text := text copyReplaceAll: '&lt;t&gt;' expandMacros with: tab.
	text := text tokensBasedOn: Character cr.
	^text collect: [:t |
		t isEmpty
			ifTrue: [Element tag: 'BR']
			ifFalse:
				[Element tag: 'P' attributes: (Array with: a copy)
					elements: (Array with: (Text new text: t))]]</body>
</methods>

<methods>
<class-id>XSL.Rule class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'template'</body>
</methods>

<methods>
<class-id>XSL.CounterIncrementCommand</class-id> <category>accessing</category>

<body package="XSL" selector="amount">amount

	self testPatternInitialized.
	^amount</body>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>
</methods>

<methods>
<class-id>XSL.CounterIncrementCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	super testPatternInitialized.
	name := self readAttribute: 'name'.
	amount := self readInteger: 'amount' default: [1].
	userData := true.</body>
</methods>

<methods>
<class-id>XSL.CounterIncrementCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| c |
	c := aProxy counterNamed: self name.
	c == nil
		ifTrue: [c := aProxy root resetCounter: self name].
	c value: c value+1.</body>
</methods>

<methods>
<class-id>XSL.CounterIncrementCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'counter-increment'</body>
</methods>

<methods>
<class-id>XSL.ElementCommand</class-id> <category>accessing</category>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>

<body package="XSL" selector="useAttrs">useAttrs

	self testPatternInitialized.
	^useAttrs</body>
</methods>

<methods>
<class-id>XSL.ElementCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	name := self readTag: 'name'.
	useAttrs := self readTagList: 'use-attribute-sets' default: [#()].</body>
</methods>

<methods>
<class-id>XSL.ElementCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| oc nm list |
	oc := aProxy childProxy.
	self processAttributeSets: aNodeContext into: oc.
	list := self xslElements.
	1 to: list size do: [:i || elm |
		elm := list at: i.
		elm process: aNodeContext into: oc].
	nm := self processAttributeValue: self name for: aNodeContext.
	nm := self resolveComputedTag: nm.
	aProxy addNode: (Element tag: nm attributes: oc attributes elements: oc children)</body>
</methods>

<methods>
<class-id>XSL.ElementCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'element'</body>
</methods>

<methods>
<class-id>XSL.NodeIterator</class-id> <category>enumeration</category>

<body package="XSL" selector="reverseDo:until:">reverseDo: aBlock until: testBlock

	| t |
	[testBlock value: current]
		whileFalse:
			[aBlock value: current.
			stack isEmpty ifTrue: [^self].
			[stack last value = 1
				ifTrue: [current := stack removeLast key]
				ifFalse:
					[t := stack last.
					t value: t value-1.
					current := t key children at: t value.
					[current isElement not or: [current children size = 0]]
						whileFalse:
							[stack add: current-&gt;current children size.
							current := current children last]].
			current isContent and: [current isText not]] whileFalse]</body>
</methods>

<methods>
<class-id>XSL.NodeIterator</class-id> <category>accessing</category>

<body package="XSL" selector="node:">node: aNode

	| nd |
	nd := current := aNode.
	stack := OrderedCollection new.
	[nd parent == nil] whileFalse:
		[stack addFirst: nd parent -&gt; (nd parent children indexOf: nd).
		nd := nd parent]</body>
</methods>

<methods>
<class-id>XSL.DenormalizedText</class-id> <category>enumerating</category>

<body package="XSL" selector="saxDo:">saxDo: aDriver

	[aDriver normalizeText: false] on: Error do: [:dummy | ].
	super saxDo: aDriver.
	[aDriver normalizeText: true] on: Error do: [:dummy | ].</body>
</methods>

<methods>
<class-id>XSL.ValueOfCommand</class-id> <category>accessing</category>

<body package="XSL" selector="expression">expression

	self testPatternInitialized.
	^expression</body>
</methods>

<methods>
<class-id>XSL.ValueOfCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	expression := self readSelectPattern: 'select'</body>
</methods>

<methods>
<class-id>XSL.ValueOfCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| elm |
	elm := self expression xpathValueIn: aNodeContext.
	(elm == nil or: [(elm := elm xpathAsString) isEmpty])
		ifFalse: [aProxy addNode: (Text new text: elm)]</body>
</methods>

<methods>
<class-id>XSL.ValueOfCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'value-of'</body>
</methods>

<methods>
<class-id>XSL.AttributeCommand</class-id> <category>testing</category>

<body package="XSL" selector="generatesAttributes">generatesAttributes

	^true</body>
</methods>

<methods>
<class-id>XSL.AttributeCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	name := self readTag: 'name'</body>
</methods>

<methods>
<class-id>XSL.AttributeCommand</class-id> <category>accessing</category>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>
</methods>

<methods>
<class-id>XSL.AttributeCommand</class-id> <category>processing</category>

<body package="XSL" selector="generateFrom:into:">generateFrom: aNode into: aProxy

	| oc computedValue nm |
	oc := aProxy childProxy.
	self xslElements do: [:elm |
		elm process: aNode into: oc].
	oc attributes isEmpty ifFalse: [self error: 'Attributes cannot have attributes'].
	computedValue := (String new: 32) writeStream.
	oc children do: [:elm |
		elm isText ifFalse: [self error: 'Attribute values can only contain text data'].
		computedValue nextPutAll: elm characterData].
	nm := self processAttributeValue: self name for: aNode.
	nm := self resolveComputedTag: nm.
	^Attribute new name: nm value: computedValue contents</body>

<body package="XSL" selector="process:into:">process: aNode into: aProxy

	| oc computedValue nm |
	aProxy children size = 0
		ifFalse: [self error: 'Attributes must all be added before content'].
	oc := aProxy childProxy.
	self xslElements do: [:elm |
		elm process: aNode into: oc].
	oc attributes isEmpty ifFalse: [self error: 'Attributes cannot have attributes'].
	computedValue := (String new: 32) writeStream.
	oc children do: [:elm |
		elm isText ifFalse: [self error: 'Attribute values can only contain text data'].
		computedValue nextPutAll: elm characterData].
	nm := self processAttributeValue: self name for: aNode.
	nm := self resolveComputedTag: nm.
	aProxy addAttribute: (Attribute new name: nm value: computedValue contents)</body>
</methods>

<methods>
<class-id>XSL.AttributeCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'attribute'</body>
</methods>

<methods>
<class-id>XSL.CopyCommand</class-id> <category>accessing</category>

<body package="XSL" selector="useAttrs">useAttrs

	self testPatternInitialized.
	^useAttrs</body>
</methods>

<methods>
<class-id>XSL.CopyCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	aNodeContext node isAttribute
		ifTrue:
			[self useAttrs isEmpty ifFalse: [self error: '&lt;xsl:copy&gt; is attempting to add attributes to an Attribute'].
			^self processAttribute: aNodeContext into: aProxy].
	aNodeContext node isElement
		ifTrue: [^self processElement: aNodeContext into: aProxy].
	(aNodeContext node isComment or: [aNodeContext node isText])
		ifTrue:
			[self useAttrs isEmpty ifFalse: [self error: '&lt;xsl:copy&gt; is attempting to add attributes to a non-Element'].
			^aProxy add: aNodeContext node copy].
	^self error: 'Copying of this node type is not yet implemented'</body>

<body package="XSL" selector="processAttribute:into:">processAttribute: aNodeContext into: aProxy

	aProxy addAttribute: (Attribute new name: aNodeContext node tag value: aNodeContext node value)</body>

<body package="XSL" selector="processElement:into:">processElement: aNodeContext into: aProxy

	| oc list |
	oc := aProxy childProxy.
	self processAttributeSets: aNodeContext into: oc.
	list := self xslElements.
	1 to: list size do: [:i || elm |
		elm := list at: i.
		elm process: aNodeContext into: oc].
	aProxy addNode: (Element tag: aNodeContext node tag attributes: oc attributes elements: oc children)</body>
</methods>

<methods>
<class-id>XSL.CopyCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	useAttrs := self readTagList: 'use-attribute-sets' default: [#()].</body>
</methods>

<methods>
<class-id>XSL.CopyCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'copy'</body>
</methods>

<methods>
<class-id>XSL.TextTemplate</class-id> <category>initialize</category>

<body package="XSL" selector="normalize">normalize

	^self</body>

<body package="XSL" selector="stripSpace">stripSpace

	^self</body>
</methods>

<methods>
<class-id>XSL.TextTemplate</class-id> <category>testing</category>

<body package="XSL" selector="isStylesheetEntry">isStylesheetEntry

	| s |
	s := text readStream.
	s skipSeparators.
	s atEnd ifFalse: [self error: 'Text contains something other than whitespace.'].
	^false</body>
</methods>

<methods>
<class-id>XSL.TextTemplate</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	self text isEmpty
		ifFalse: [aProxy addNode: (Text new text: self text)]</body>
</methods>

<methods>
<class-id>XSL.CommentCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| oc str |
	oc := aProxy childProxy.
	self xslElements do: [:elm |
		elm process: aNodeContext into: oc].
	oc attributes isEmpty ifFalse: [self error: 'Comments do not support attributes'].
	str := (String new: 128) writeStream.
	oc children do: [:nd |
		nd isText ifFalse: [self error: 'Comments can only contain text, not elements, pi''s, or other comments'].
		str nextPutAll: nd characterData].
	str := str contents.
		"Need to do this twice to handle comments with a long run of -----"
	str := str copyReplaceAll: '--' with: '- -'.
	str := str copyReplaceAll: '--' with: '- -'.
	str last = $- ifTrue: [str := str copyWith: $ ].
	aProxy addNode: (Comment new text: str)</body>
</methods>

<methods>
<class-id>XSL.CommentCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'comment'</body>
</methods>

<methods>
<class-id>XSL.RuleDatabase</class-id> <category>importance</category>

<body package="XSL" selector="importance">importance

	^currentImportance</body>

<body package="XSL" selector="importance:">importance: aValueHolder

	currentImportance := aValueHolder</body>

<body package="XSL" selector="raiseImportance">raiseImportance

	currentImportance := (currentImportance value+1) asValue</body>

<body package="XSL" selector="replaceImportance:">replaceImportance: oldValue

	variables do: [:clist |
		clist do: [:c |
			c replaceImportance: oldValue with: currentImportance]].
	namedTemplates do: [:mlist |
		mlist do: [:m |
			m replaceImportance: oldValue with: currentImportance]].
	rules do: [:r |
		r replaceImportance: oldValue with: currentImportance]</body>
</methods>

<methods>
<class-id>XSL.RuleDatabase</class-id> <category>loading</category>

<body package="XSL" selector="addAttributeSet:">addAttributeSet: anAttributeSet

	| all |
	anAttributeSet importanceHolder: currentImportance.
	all := attributeSets at: anAttributeSet name
			ifAbsentPut: [OrderedCollection new].
	all add: anAttributeSet</body>

<body package="XSL" selector="addNamedTemplate:">addNamedTemplate: aRule

	| all |
	aRule importanceHolder: currentImportance.
	all := namedTemplates at: aRule name
			ifAbsentPut: [OrderedCollection new].
	(all contains: [:c | c importance = currentImportance value])
		ifTrue: [self error: ('There are two named templates named &lt;1s&gt; with the same importance' expandMacrosWith: aRule name)].
	all add: aRule</body>

<body package="XSL" selector="addRule:">addRule: aRule

	aRule importanceHolder: currentImportance.
	rules add: aRule</body>

<body package="XSL" selector="addRuleSet:topLevel:">addRuleSet: anXSLCommand topLevel: isTopLevel

	anXSLCommand purgeUnimportant.
	isTopLevel
		ifTrue: [anXSLCommand topLevelAddToRuleDB: self]
		ifFalse: [anXSLCommand addToRuleDB: self].</body>

<body package="XSL" selector="addVariable:">addVariable: aVariable

	| all |
	aVariable importanceHolder: currentImportance.
	all := variables at: aVariable name
			ifAbsentPut: [OrderedCollection new].
	(all contains: [:c | c importance = currentImportance value])
		ifTrue: [self error: ('There are two variables named &lt;1s&gt; with the same importance' expandMacrosWith: aVariable name)].
	all add: aVariable</body>

<body package="XSL" selector="attributesForSet:">attributesForSet: setName

	| list map |
	list := attributeSets at: setName
		ifAbsent: [self error: ('No attribute set named "&lt;1s&gt;".' expandMacrosWith: setName asString)].
	map := Dictionary new.
	list do: [:as |
		(as allAttributesFrom: self) do: [:attr |
			(map at: attr name ifAbsentPut: [SortedCollection sortBlock: [:a1 :a2 | a1 key &gt; a2 key]])
				add: as importance-&gt;attr]].
	list := OrderedCollection new.
	map do: [:singleList |
		(singleList size &gt; 1 and: [(singleList at: 1) key = (singleList at: 2) key])
			ifTrue: [self error: ('Attribute set "&lt;1s&gt;" includes more than one definition of the attribute "&lt;2s&gt;".'
						expandMacrosWith: setName asString
						with: singleList first name asString)].
		list add: singleList first value].
	^list</body>

<body package="XSL" selector="bindVariableValues:arguments:">bindVariableValues: aNodeContext arguments: argDictionary

	variables do: [:var |
		var process: aNodeContext into: nil takeArgumentsFrom: argDictionary]</body>

<body package="XSL" selector="normalizeRules">normalizeRules

	normalized ifTrue: [^self].
	normalized := true.
	self normalizeVariables.
	namedTemplates keys do: [:nm || clist |
		clist := namedTemplates at: nm.
		(clist collect: [:c | c importance]) asSet size = clist size
			ifFalse: [self error: 'Named template named "',nm,'" has more than one definition with the same importance'].
		namedTemplates at: nm put: (clist asSortedCollection: [:c1 :c2 | c1 importance &lt; c2 importance]) last].
	namedTemplates do: [:m | m normalize].
	rules do: [:r | r normalize].</body>

<body package="XSL" selector="normalizeVariables">normalizeVariables

	| unsorted sorted lastSize list |
	variables class == Dictionary ifFalse: [^self].
	variables keys do: [:nm || clist |
		clist := variables at: nm.
		(clist collect: [:c | c importance]) asSet size = clist size
			ifFalse: [self error: 'Variable named "',nm,'" has more than one definition with the same importance'].
		variables at: nm put: (clist asSortedCollection: [:c1 :c2 | c1 importance &lt; c2 importance]) last].
	variables do: [:c | c normalize].
	unsorted := variables asOrderedCollection.
	sorted := OrderedCollection new.
	lastSize := -1.
	[sorted size = lastSize] whileFalse:
		[lastSize := sorted size.
		unsorted copy do: [:var |
			list := var expression xpathUsedVarNames.
			list := list reject: [:nm | sorted includes: nm].
			list isEmpty
				ifTrue:
					[sorted add: var name.
					unsorted remove: var]]].
	unsorted isEmpty ifFalse: [self error: 'There is a cycle of reference between the variables'].
	variables := sorted collect: [:v | variables at: v].</body>

<body package="XSL" selector="readFileNamed:">readFileNamed: aFilename

	| doc |
	self initURI: 'file' name: aFilename asString.
	doc := XMLParser
		processDocumentInFilename: aFilename
		beforeScanDo:
			[:parser |
			parser builder: XSLNodeBuilder new.
			parser validate: false].
	self addRuleSet: doc root topLevel: true</body>

<body package="XSL" selector="readStream:">readStream: aStream

	self readStream: aStream topLevel: true</body>

<body package="XSL" selector="readStream:topLevel:">readStream: aStream topLevel: isTopLevel

	| doc parser |
	parser := XMLParser on: aStream.
	parser builder: XSLNodeBuilder new.
	parser validate: false.
	doc := parser scanDocument.
	self addRuleSet: doc root topLevel: isTopLevel</body>

<body package="XSL" selector="readString:">readString: aString

	| doc |
	self initURI: 'file' name: (Filename currentDirectory construct: 'xxx').
	doc := XMLParser
		processDocumentString: aString
		beforeScanDo:
			[:parser |
			parser builder: XSLNodeBuilder new.
			parser validate: false].
	self addRuleSet: doc root topLevel: true</body>

<body package="XSL" selector="resolveAttributesForSet:">resolveAttributesForSet: setName

	| list |
	list := attributeSets at: setName
		ifAbsent: [self error: ('No attribute set named "&lt;1s&gt;".' expandMacrosWith: setName asString)].</body>

<body package="XSL" selector="setOutput:">setOutput: anOutputCommand

	output := anOutputCommand</body>

<body package="XSL" selector="uriStack">uriStack

	^uriStack</body>
</methods>

<methods>
<class-id>XSL.RuleDatabase</class-id> <category>processing</category>

<body package="XSL" selector="chooseBestRule:for:">chooseBestRule: ruleList for: aNodeContext

	| best |
	ruleList size = 1 ifTrue: [^ruleList first].
	best := ruleList asSortedCollection:
					[:r1 :r2 | r1 importance &gt;= r2 importance].
	best := best asOrderedCollection select: [:r1 | r1 importance = best first importance].
	best size = 1 ifTrue: [^best first].
	best := best collect: [:r1 | r1 priority -&gt; r1].
	best := best asSortedCollection: [:a1 :a2 | a1 &gt; a2].
	best := best asOrderedCollection select: [:a1 | a1 key = best first key].
	best := best collect: [:a | a value].
	best size = 1 ifTrue: [^best first].
	best size = 0 ifFalse:
		[self halt: 'Conflicting rules for ', aNodeContext node simpleDescription, ', use priority to rank the rules.'.
		^best last].
	^nil</body>

<body package="XSL" selector="process:">process: aDocument

	^self process: aDocument arguments: Dictionary new</body>

<body package="XSL" selector="process:arguments:">process: aDocument arguments: passedArguments

	| doc baseDoc baseVars |
	self normalizeRules.
	doc := DocumentFragment new.
	baseVars := Dictionary new.
	baseDoc := XSLNodeContext new
			add: aDocument;
			index: 1;
			variables: baseVars;
			db: self.
	self bindVariableValues: baseDoc arguments: passedArguments.
	baseDoc variables: (ChainedDictionary new parent: baseVars).
	(self process: baseDoc into: ElementProxy new mode: nil) children do: [:elm |
		doc addNode: elm].
	doc addNamespaceDefinitions.
	^doc</body>

<body package="XSL" selector="process:into:mode:">process: aNodeContext into: aProxy mode: mode

	| rule list |
	list := rules select: [:r | r match: aNodeContext].
	list := list select: [:r | r modeIsLike: mode].
	rule := self chooseBestRule: list for: aNodeContext.
	rule == nil ifFalse: [rule process: aNodeContext into: aProxy arguments: #()].
	^aProxy</body>

<body package="XSL" selector="ruleMatching:mode:">ruleMatching: aNodeContext mode: mode

	| rule list |
	list := OrderedCollection new: 5.
	1 to: rules size do: [:i |
		rule := rules at: i.
		((rule modeIsLike: mode) and: [rule match: aNodeContext])
			ifTrue: [list add: rule]].
"	list := rules select: [:r | r match: aNodeContext].
	list := list select: [:r | r modeIsLike: mode]."
	rule := self chooseBestRule: list for: aNodeContext.
	^rule</body>

<body package="XSL" selector="ruleNamed:">ruleNamed: aName

	^namedTemplates at: aName ifAbsent: []</body>
</methods>

<methods>
<class-id>XSL.RuleDatabase</class-id> <category>initialize</category>

<body package="XSL" selector="initialize">initialize

	| baseRule action builtinImportance |
	normalized := false.
	rules := OrderedCollection new.
	variables := Dictionary new.
	namedTemplates := Dictionary new.
	attributeSets := Dictionary new.
	currentImportance := 1 asValue.
	builtinImportance := 0 asValue.

	action := ApplyTemplatesCommand new.
	baseRule := Rule new.
	baseRule mode: #any.
	baseRule attributes: (Array with: (Attribute name: 'match' value: '*|/')).
	baseRule elements: (Array with: action).
	baseRule importanceHolder: builtinImportance.
	rules add: baseRule.

	action := ValueOfCommand new.
	action attributes: (Array with: (Attribute name: 'select' value: '.')).
	baseRule := Rule new.
	baseRule mode: #any.
	baseRule attributes: (Array with: (Attribute name: 'match' value: 'text()')).
	baseRule elements: (Array with: action).
	baseRule importanceHolder: builtinImportance.
	rules add: baseRule</body>

<body package="XSL" selector="initURI:name:">initURI: aProtocol name: aName

	uriStack == nil
		ifTrue: [uriStack := OrderedCollection with: aProtocol-&gt;(aName copy asString replaceAll: Filename separator with: $/)].</body>
</methods>

<methods>
<class-id>XSL.RuleDatabase</class-id> <category>accessing</category>

<body package="XSL" selector="output">output

	output == nil ifTrue: [output := OutputCommand new].
	^output</body>

<body package="XSL" selector="outputMethodFor:">outputMethodFor: aDocument

	| rt |
	self output method = #auto ifFalse: [^self output method].
	rt := aDocument root.
	(rt notNil and: [rt tag namespace isEmpty and: [rt tag type asLowercase = 'html']])
		ifTrue: [^'html'].
	^'xml'</body>
</methods>

<methods>
<class-id>XSL.RuleDatabase class</class-id> <category>XML for examples</category>

<body package="XSL" selector="constructXML">constructXML
	"RuleDatabase constructXML"

	^'&lt;doc a="1" b="2"&gt;
	&lt;title c="3" d="4"&gt;An example&lt;/title&gt;
	&lt;p k="xyz"&gt;This is a test.&lt;/p&gt;
	&lt;p&gt;This is &lt;emph&gt;another&lt;/emph&gt; test.&lt;/p&gt;
	&lt;/doc&gt;'</body>

<body package="XSL" selector="constructXSL">constructXSL

	^'&lt;?xml version=''1.0''?&gt;
	&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
				indent-result="yes"&gt;
		&lt;xsl:variable name="tag" select="$tag2"/&gt;
		&lt;xsl:variable name="tag2" select="''new''"/&gt;

		&lt;xsl:template match="*"&gt;
			&lt;xsl:element name="{$tag}-{name(.)}"&gt;
				&lt;xsl:for-each select="@*"&gt;
					&lt;xsl:attribute name="{name(.)}-copy"&gt;
						..&lt;xsl:value-of select="."/&gt;..
					&lt;/xsl:attribute&gt;
				&lt;/xsl:for-each&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/xsl:element&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="p" priority="1"&gt;
			&lt;xsl:copy&gt;
				&lt;xsl:apply-templates select="@*|*|text()"/&gt;
			&lt;/xsl:copy&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="p/@*"&gt;
			&lt;xsl:copy&gt;
				&lt;xsl:apply-templates select="text()"/&gt;
			&lt;/xsl:copy&gt;
		&lt;/xsl:template&gt;
	&lt;/xsl:stylesheet&gt;'</body>

<body package="XSL" selector="macroXML">macroXML

	^'&lt;?xml version="1.0"?&gt;

	&lt;doc&gt;
		&lt;p&gt;a paragraph&lt;/p&gt;
		&lt;p&gt;another paragraph&lt;/p&gt;
		&lt;warning&gt;the warning&lt;/warning&gt;
		&lt;p&gt;closing paragraph&lt;/p&gt;
		&lt;warning&gt;warning 2&lt;/warning&gt;
		&lt;warning&gt;warning 3&lt;/warning&gt;
		&lt;list&gt;
			&lt;item&gt;&lt;surname&gt;Smith&lt;/surname&gt;&lt;name&gt;Joe&lt;/name&gt;&lt;MI&gt;G.&lt;/MI&gt;&lt;/item&gt;
			&lt;item&gt;&lt;surname&gt;Jones&lt;/surname&gt;&lt;name&gt;John&lt;/name&gt;&lt;MI&gt;P.&lt;/MI&gt;&lt;/item&gt;
			&lt;item&gt;&lt;surname&gt;Smith&lt;/surname&gt;&lt;name&gt;Bill&lt;/name&gt;&lt;MI&gt;M.&lt;/MI&gt;&lt;/item&gt;
			&lt;item&gt;&lt;surname&gt;Bell&lt;/surname&gt;&lt;name&gt;Alexander&lt;/name&gt;&lt;MI&gt;G.&lt;/MI&gt;&lt;/item&gt;
			&lt;item&gt;&lt;surname&gt;Smith&lt;/surname&gt;&lt;name&gt;Bill&lt;/name&gt;&lt;MI&gt;A.&lt;/MI&gt;&lt;/item&gt;
		&lt;/list&gt;
	&lt;/doc&gt;'</body>

<body package="XSL" selector="macroXSL">macroXSL

	^'&lt;?xml version=''1.0''?&gt;
	&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
				indent-result="yes"&gt;
		&lt;xsl:template name="warning-para"&gt;
			&lt;xsl:param name="format" select="''1. ''"/&gt;
			&lt;xsl:param name="content"/&gt;
			&lt;box font-color="red"&gt;
				&lt;xsl:number format="{$format}"/&gt;
				&lt;xsl:text&gt;Warning! &lt;/xsl:text&gt;
				&lt;xsl:copy-of select="$content"/&gt;
			&lt;/box&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match=''p|doc''&gt;
			&lt;xsl:copy&gt;&lt;xsl:apply-templates/&gt;&lt;/xsl:copy&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match=''warning''&gt;
			&lt;xsl:call-template name="warning-para"&gt;
				&lt;xsl:with-param name="format" select="''A. ''"/&gt;
				&lt;xsl:with-param name="content"&gt;
					&lt;xsl:apply-templates/&gt;
					&lt;xsl:text&gt; (see appendix)&lt;/xsl:text&gt;
				&lt;/xsl:with-param&gt;
			&lt;/xsl:call-template&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match=''list''&gt;
			&lt;list&gt;
				&lt;xsl:apply-templates select="item"&gt;
					&lt;xsl:sort select="surname" order="ascending"/&gt;
					&lt;xsl:sort select="name" order="descending"/&gt;
				&lt;/xsl:apply-templates&gt;
			&lt;/list&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match=''item''&gt;
			&lt;name&gt;
				&lt;xsl:value-of select="name"/&gt;
				&lt;xsl:text&gt; &lt;/xsl:text&gt;
				&lt;xsl:value-of select="MI"/&gt;
				&lt;xsl:text&gt; &lt;/xsl:text&gt;
				&lt;xsl:value-of select="surname"/&gt;
			&lt;/name&gt;
		&lt;/xsl:template&gt;

	&lt;/xsl:stylesheet&gt;'</body>

<body package="XSL" selector="numberedSourceData">numberedSourceData

	^'1. Overview
2. Tree Construction
	2.1 Overview
	2.2 Stylesheet Structure
	2.3 Processing Model
	2.4 Data Model
		2.4.1 Root Node
		2.4.2 Element Nodes
		2.4.3 Attribute Nodes
		2.4.4 Character Data
		2.4.5 Whitespace Stripping
	2.5 Template Rules
		2.5.1 Conflict Resolution for Template Rules
		2.5.2 Built-in Template Rule
	2.6 Patterns
		2.6.1 Alternative Patterns
		2.6.2 Matching on Element Ancestry
		2.6.3 Anchors
		2.6.4 Matching the Root Node
		2.6.5 Matching on Element Types
		2.6.6 Qualifiers
		2.6.7 Matching on Children
		2.6.8 Matching on Attributes
		2.6.9 Matching on Position
		2.6.10 Whitespace in Patterns
		2.6.11 Specificity
	2.7 Templates
		2.7.1 Overview
		2.7.2 Literal Result Elements
		2.7.3 Named Attribute Sets
		2.7.4 Literal Text in Templates
		2.7.5 Processing with xsl:process-children
		2.7.6 Processing with xsl:process
		2.7.7 Direct Processing
		2.7.8 Numbering in the Source Tree
		2.7.9 Number to String Conversion Attributes
		2.7.10 Conditionals within a Template
		2.7.11 Computing Generated Text
		2.7.12 String Constants
		2.7.13 Macros
	2.8 Style Rules
	2.9 Combining Stylesheets
		2.9.1 Stylesheet Import
		2.9.2 Stylesheet Inclusion
		2.9.3 Embedding Stylesheets
	2.10 Extensibility
3. Formatting Objects
	3.1 Introduction
	3.2 Notations Used in this Section
	3.3 Formatting Objects and Their Properties
	3.4 Formatting Objects to be Defined in Subsequent Drafts
	3.5 Page-sequence Layout Object
		3.5.1 Purpose
		3.5.2 Formatting Object Summary
		3.5.3 Formatting Object''s Formal Specification
		3.5.4 To Resolve
	3.6 Simple-page-master Layout Object
		3.6.1 Purpose
		3.6.2 Formatting Object Summary
		3.6.3 Formatting Object''s Formal Specification
		3.6.4 To Resolve
A. DTD for XSL Stylesheets
B. References
	B.1 Normative References
	B.2 Other References
C. Examples (Non-Normative)
D. Design Principles (Non-Normative)
E. Acknowledgements (Non-Normative)
'</body>

<body package="XSL" selector="numberedXML">numberedXML
	"RuleDatabase numberedXML"

	| src stack str depth parent title tag |
	stack := OrderedCollection new.
	stack add: (Element tag: 'doc').
	src := self numberedSourceData readStream.
	[src atEnd] whileFalse:
		[str := src upTo: Character cr.
		depth := str occurrencesOf: Character tab.
		str := str copyFrom: depth+1 to: str size.
		tag := depth = 0
			ifTrue: [str first isDigit
				ifTrue: ['chapter']
				ifFalse: ['appendix']]
			ifFalse: [#('section' 'subsection') at: depth].
		str := str copyFrom: (str indexOf: $ )+1 to: str size.
		[depth+1 = stack size] whileFalse: [stack removeLast].
		parent := stack last.
		title := Text text: str.
		title := Element tag: 'title' elements: (Array with: title).
		title := Element tag: tag elements: (Array with: title).
		stack addLast: title.
		parent elements: (parent children copyWith: title)].
	^stack first printString</body>

<body package="XSL" selector="numberedXML2">numberedXML2
	"RuleDatabase numberedXML2"

	| src stack str depth title tag |
	stack := OrderedCollection new.
	stack add: (Element tag: 'doc').
	src := self numberedSourceData readStream.
	[src atEnd] whileFalse:
		[str := src upTo: Character cr.
		depth := str occurrencesOf: Character tab.
		str := str copyFrom: depth+1 to: str size.
		tag := depth = 0
			ifTrue: ['H1']
			ifFalse: [#('H2' 'H3' 'H4') at: depth].
		str := str copyFrom: (str indexOf: $ )+1 to: str size.
		title := Text text: str.
		title := Element tag: tag elements: (Array with: title).
		stack last elements: (stack last children copyWith: title)].
	^stack first printString</body>

<body package="XSL" selector="numberedXSL">numberedXSL

	^'&lt;?xml version=''1.0''?&gt;
	&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
				xmlns:fo="http://www.w3.org/1999/XSL/Transform/FO"
				result-ns="fo"
				indent-result="yes"&gt;
		&lt;xsl:template match="doc"&gt;
			&lt;html&gt;
			&lt;body&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/body&gt;
			&lt;/html&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="*" priority="-10"&gt;
			&lt;UL&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/UL&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="title"&gt;
			&lt;LI&gt;
				&lt;xsl:number level="multi"
						count="chapter|section|subsection"
						format="1. "/&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/LI&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="appendix//title" priority="1"&gt;
			&lt;LI&gt;
				&lt;xsl:number level="multi"
						count="appendix|section|subsection"
						format="I.a. "/&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/LI&gt;
		&lt;/xsl:template&gt;
	&lt;/xsl:stylesheet&gt;'</body>

<body package="XSL" selector="numberedXSL1">numberedXSL1

	^'&lt;?xml version=''1.0''?&gt;
	&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
				xmlns:fo="http://www.w3.org/1999/XSL/Transform/FO"
				result-ns="fo"
				indent-result="yes"&gt;
		&lt;xsl:template match="doc"&gt;
			&lt;html&gt;
			&lt;body&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/body&gt;
			&lt;/html&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="*" priority="-10"&gt;
			&lt;UL&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/UL&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="title"&gt;
			&lt;LI&gt;
				&lt;xsl:number level="single"
						count="chapter|section|subsection"
						format="1. "/&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/LI&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="appendix//title" priority="1"&gt;
			&lt;LI&gt;
				&lt;xsl:number level="single"
						count="appendix|section|subsection"
						format="I. "/&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/LI&gt;
		&lt;/xsl:template&gt;
	&lt;/xsl:stylesheet&gt;'</body>

<body package="XSL" selector="numberedXSL2">numberedXSL2

	^'&lt;?xml version=''1.0''?&gt;
	&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
				xmlns:fo="http://www.w3.org/1999/XSL/Transform/FO"
				result-ns="fo"
				indent-result="yes"&gt;
		&lt;xsl:template match="doc"&gt;
			&lt;html&gt;
			&lt;body&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/body&gt;
			&lt;/html&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="H3"&gt;
			&lt;fo:block&gt;
				&lt;xsl:number level="any" count="H1"/&gt;
				&lt;xsl:text&gt;.&lt;/xsl:text&gt;
				&lt;xsl:number level="any" from="H1" count="H2"/&gt;
				&lt;xsl:text&gt;.&lt;/xsl:text&gt;
				&lt;xsl:number level="any" from="H2" count="H3"/&gt;
				&lt;xsl:text&gt; &lt;/xsl:text&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/fo:block&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="H2"&gt;
			&lt;fo:block&gt;
				&lt;xsl:number level="any" count="H1"/&gt;
				&lt;xsl:text&gt;.&lt;/xsl:text&gt;
				&lt;xsl:number level="any" from="H1" count="H2"/&gt;
				&lt;xsl:text&gt; &lt;/xsl:text&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/fo:block&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="H1"&gt;
			&lt;fo:block&gt;
				&lt;xsl:number level="any" count="H1"/&gt;
				&lt;xsl:text&gt; &lt;/xsl:text&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/fo:block&gt;
		&lt;/xsl:template&gt;

	&lt;/xsl:stylesheet&gt;'</body>

<body package="XSL" selector="patternsXML">patternsXML

	^'&lt;?xml version="1.0"?&gt;

	&lt;!DOCTYPE a [
		&lt;!ELEMENT a (a | b | c)*&gt;
		&lt;!ELEMENT b (#PCDATA | c)*&gt;
		&lt;!ELEMENT c (#PCDATA)&gt;
		&lt;!ATTLIST a
			x ID #IMPLIED
			y CDATA #IMPLIED&gt;
	]&gt;

	&lt;a x="top"&gt;
		&lt;a x="c1" y="tester"&gt;
			&lt;b&gt;&lt;c&gt;title&lt;/c&gt;
			body of chapter1&lt;/b&gt;
			&lt;b&gt;&lt;c&gt;subsection&lt;/c&gt;
			more of chapter 1&lt;/b&gt;
		&lt;/a&gt;
		&lt;a x="c2"&gt;
			&lt;b&gt;&lt;c&gt;title2&lt;/c&gt;
			body of chapter 2&lt;/b&gt;
		&lt;/a&gt;
	&lt;/a&gt;'</body>

<body package="XSL" selector="patternsXSL">patternsXSL

	^'&lt;?xml version=''1.0''?&gt;
	&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
				indent-result="yes"&gt;
		&lt;xsl:template match=''/''&gt;
			&lt;xsl:comment&gt;--------------------&lt;/xsl:comment&gt;
			&lt;xsl:apply-templates/&gt;
			&lt;xsl:pi name="vwst"&gt;arg1="class" arg2="Array"&lt;/xsl:pi&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match=''a''&gt;
			&lt;div&gt;&lt;xsl:apply-templates/&gt;&lt;/div&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match=''b''&gt;
			&lt;span&gt;&lt;xsl:apply-templates/&gt;&lt;/span&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match=''c''&gt;
			&lt;H1&gt;&lt;xsl:apply-templates/&gt;&lt;/H1&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match=''a[@y="tester"]//c'' priority="1"&gt;
			&lt;H1 attr="test"&gt;&lt;xsl:apply-templates/&gt;&lt;/H1&gt;
			&lt;H2 attr="test"&gt;&lt;xsl:value-of select=''id("c2")/b/c''/&gt;&lt;/H2&gt;
		&lt;/xsl:template&gt;

	&lt;/xsl:stylesheet&gt;'</body>

<body package="XSL" selector="sampleXML">sampleXML

	^'&lt;doc&gt;
	&lt;title&gt;An example&lt;/title&gt;
	&lt;p&gt;This is a test.&lt;/p&gt;
	&lt;p&gt;This is &lt;emph&gt;another&lt;/emph&gt; test.&lt;/p&gt;
	&lt;/doc&gt;'</body>

<body package="XSL" selector="sampleXSL">sampleXSL

	^'&lt;?xml version=''1.0''?&gt;
	&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
				xmlns:fo="http://www.w3.org/1999/XSL/Transform/FO"
				result-ns="fo"
				indent-result="yes"&gt;
		&lt;xsl:template match=''/''&gt;
			&lt;fo:page-sequence font-family="serif"&gt;
				&lt;fo:simple-page-master name=''scrolling''/&gt;
				&lt;fo:queue queue-name=''body''&gt;
					&lt;xsl:apply-templates/&gt;
				&lt;/fo:queue&gt;
			&lt;/fo:page-sequence&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="title"&gt;
			&lt;fo:block font-weight="bold"&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/fo:block&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="p"&gt;
			&lt;fo:block&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/fo:block&gt;
		&lt;/xsl:template&gt;

		&lt;xsl:template match="emph"&gt;
			&lt;fo:sequence font-style="italic"&gt;
				&lt;xsl:apply-templates/&gt;
			&lt;/fo:sequence&gt;
		&lt;/xsl:template&gt;

	&lt;/xsl:stylesheet&gt;'</body>
</methods>

<methods>
<class-id>XSL.RuleDatabase class</class-id> <category>examples</category>

<body package="XSL" selector="allTest">allTest
	"XSL.RuleDatabase allTest"

	| sel |
	sel := self class selectors select: [:s | 'test*' match: s].
	sel asSortedCollection do:
		[:s |
		self perform: s].</body>

<body package="XSL" selector="defaultDirectoryOnCancelDo:">defaultDirectoryOnCancelDo: aBlock

	| default |
	default := ('..' asFilename construct: 'xml-st') asString.
	default := Dialog requestFileName: 'Where are the example files?'
			default: default.
	default = '' ifTrue: [^aBlock value].
	default := default asFilename.
	^default</body>

<body package="XSL" selector="store:on:">store: document on: filename

	(filename asFilename
			withEncoding: #UTF_8) writeStream
		print: document;
		close</body>

<body package="XSL" selector="test">test
	"RuleDatabase test"

	| test doc |
	test := self new.
	test readString: self sampleXSL.
	doc := XMLParser
			processDocumentString: self sampleXML
			beforeScanDo: [:parser | parser validate: false].
	^test process: doc</body>

<body package="XSL" selector="test2">test2
	"RuleDatabase test2"

	| test doc default result |
	default := self defaultDirectoryOnCancelDo: [^self].
	test := self new.
	test readFileNamed: (default construct: 'activityinfo.xsl').
	doc := XMLParser
			processDocumentInFilename: (default construct: 'activityinfo.xml')
			beforeScanDo: [:parser | parser validate: false].
	result := test process: doc.
	self store: result on: 'activityinfo.html'</body>

<body package="XSL" selector="test2a">test2a
	"RuleDatabase test2a"

	| test doc default result |
	default := self defaultDirectoryOnCancelDo: [^self].
	test := self new.
	test readFileNamed: (default construct: 'activityinfo2.xsl').
	doc := XMLParser
			processDocumentInFilename: (default construct: 'activityinfo.xml')
			beforeScanDo: [:parser | parser validate: false].
	result := test process: doc.
	self store: result on: 'activityinfo2.html'.</body>

<body package="XSL" selector="test2b">test2b
	"RuleDatabase test2b"

	| test doc default result |
	default := self defaultDirectoryOnCancelDo: [^self].
	test := self new.
	test readFileNamed: (default construct: 'activityinfo3.xsl').
	doc := XMLParser
			processDocumentInFilename: (default construct: 'activityinfo.xml')
			beforeScanDo: [:parser | parser validate: false].
	result := test process: doc.
	self store: result on: 'activityinfo3.html'.</body>

<body package="XSL" selector="test3">test3
	"RuleDatabase test3"

	| test doc default result |
	default := self defaultDirectoryOnCancelDo: [^self].
	test := self new.
	test readFileNamed: (default construct: 'listgen.xsl').
	doc := XMLParser
			processDocumentInFilename: (default construct: 'listgen.xml')
			beforeScanDo: [:parser | parser validate: false].
	result := test process: doc.
	self store: result on: 'listgen.html'.</body>

<body package="XSL" selector="test4">test4
	"RuleDatabase test4"

	| test doc |
	test := self new.
	test readString: self numberedXSL.
	doc := XMLParser
			processDocumentString: self numberedXML
			beforeScanDo: [:parser | parser validate: false].
	^test process: doc</body>

<body package="XSL" selector="test4a">test4a
	"RuleDatabase test4a"

	| test doc |
	test := self new.
	test readString: self numberedXSL1.
	doc := XMLParser
			processDocumentString: self numberedXML
			beforeScanDo: [:parser | parser validate: false].
	^test process: doc</body>

<body package="XSL" selector="test4b">test4b
	"RuleDatabase test4b"

	| test doc |
	test := self new.
	test readString: self numberedXSL2.
	doc := XMLParser
			processDocumentString: self numberedXML2
			beforeScanDo: [:parser | parser validate: false].
	^test process: doc</body>

<body package="XSL" selector="test5">test5
	"RuleDatabase test5"

	| test doc |
	test := self new.
	test readString: self constructXSL.
	doc := XMLParser
			processDocumentString: self constructXML
			beforeScanDo: [:parser | parser validate: false].
	^test process: doc</body>

<body package="XSL" selector="test6">test6
	"RuleDatabase test6"

	| test doc |
	test := self new.
	test readString: self patternsXSL.
	doc := XMLParser
			processDocumentString: self patternsXML.
	^test process: doc</body>

<body package="XSL" selector="test7">test7
	"RuleDatabase test7"

	| test doc |
	test := self new.
	test readString: self macroXSL.
	doc := XMLParser
			processDocumentString: self macroXML
			beforeScanDo: [:parser | parser validate: false].
	^test process: doc</body>
</methods>

<methods>
<class-id>XSL.RuleDatabase class</class-id> <category>instance creation</category>

<body package="XSL" selector="new">new

	^super new initialize</body>
</methods>

<methods>
<class-id>XSL.TextCommand</class-id> <category>testing</category>

<body package="XSL" selector="shouldStrip">shouldStrip

	^false</body>
</methods>

<methods>
<class-id>XSL.TextCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	(self readAttribute: 'disable-output-escaping' default: ['no']) = 'yes'
		ifTrue: [aProxy addNode: (DenormalizedText new text: self characterData)]
		ifFalse: [aProxy addNode: (Text new text: self characterData)]</body>
</methods>

<methods>
<class-id>XSL.TextCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'text'</body>
</methods>

<methods>
<class-id>XSL.ChooseOtherwiseCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	self shouldNotImplement</body>
</methods>

<methods>
<class-id>XSL.ChooseOtherwiseCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'otherwise'</body>
</methods>

<methods>
<class-id>XSL.XSLNodeContext</class-id> <category>accessing</category>

<body package="XSL" selector="db">db

	^db</body>

<body package="XSL" selector="db:">db: aRuleDatabase

	db := aRuleDatabase</body>

<body package="XSL" selector="mode">mode

	^mode</body>

<body package="XSL" selector="mode:">mode: aSymbol

	mode := aSymbol</body>
</methods>

<methods>
<class-id>XSL.NumberFormat</class-id> <category>accessing</category>

<body package="XSL" selector="format">format

	^format</body>

<body package="XSL" selector="format:">format: s

	format := s</body>

<body package="XSL" selector="separator">separator

	^separator</body>

<body package="XSL" selector="separator:">separator: s

	separator := s</body>
</methods>

<methods>
<class-id>XSL.NumberFormat</class-id> <category>printing</category>

<body package="XSL" selector="printOn:">printOn: aStream

	format == nil ifFalse: [aStream nextPutAll: format].
	separator == nil ifFalse: [aStream nextPutAll: separator].
	(nextLink == nil or: [nextLink == self])
		ifFalse: [nextLink printOn: aStream].</body>
</methods>

<methods>
<class-id>XSL.ForEachCommand</class-id> <category>accessing</category>

<body package="XSL" selector="addSortBlock:">addSortBlock: aSortCommand

	sortList == nil ifTrue: [sortList := #()].
	sortList := sortList copyWith: aSortCommand</body>

<body package="XSL" selector="defineVariable:">defineVariable: aVariable

	variables add: aVariable.
	self parent defineVariable: aVariable</body>

<body package="XSL" selector="selectPattern">selectPattern

	self testPatternInitialized.
	^selectPattern</body>

<body package="XSL" selector="sortList">sortList

	^sortList</body>
</methods>

<methods>
<class-id>XSL.ForEachCommand</class-id> <category>initialize</category>

<body package="XSL" selector="initialize">initialize

	super initialize.
	elements := nil.
	variables := OrderedCollection new: 0.</body>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	selectPattern := self readSelectPattern: 'select'</body>
</methods>

<methods>
<class-id>XSL.ForEachCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| list elms listCopy |
	elms := self xslElements.
	list := self selectAll: aNodeContext withPattern: self selectPattern.
	self sortList == nil
		ifTrue: [list documentOrder; ensureSorted]
		ifFalse:
			[listCopy := list shallowCopy.
			list sort: [:n1 :n2 | self collate: n1 to: n2 within: listCopy]].
	list reset.
	[list atEnd]
		whileFalse:
			[list next.
			1 to: elms size do: [:i || elm |
				elm := elms at: i.
				elm process: list into: aProxy]]</body>
</methods>

<methods>
<class-id>XSL.ForEachCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'for-each'</body>
</methods>

<methods>
<class-id>XSL.CopyOfCommand</class-id> <category>processing</category>

<body package="XSL" selector="copyNode:to:">copyNode: n to: aContainer

	| new |
	n isDocument
		ifTrue: [^self copyNode: n root to: aContainer].
	n isAttribute
		ifTrue: [^aContainer addAttribute: n copy].
	n isElement
		ifFalse: [^aContainer addNode: n copy].
	new := n class tag: n tag attributes: (n attributes collect: [:a | a copy]) elements: nil.
	n children do: [:c | self copyNode: c to: new].
	aContainer addNode: new.</body>

<body package="XSL" selector="copyNodes:into:">copyNodes: sortedNodes into: aProxy

	sortedNodes do: [:n | self copyNode: n to: aProxy].</body>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| elm |
	elm := self expression xpathValueIn: aNodeContext.
	elm xpathIsNodeSet
		ifTrue: [self copyNodes: elm sortedNodes into: aProxy]
		ifFalse: [(elm isKindOf: ElementProxy)
			ifTrue: [self copyNodes: elm children into: aProxy]
			ifFalse: [aProxy add: (Text new text: elm xpathAsString value)]]</body>
</methods>

<methods>
<class-id>XSL.CopyOfCommand</class-id> <category>accessing</category>

<body package="XSL" selector="expression">expression

	self testPatternInitialized.
	^expression</body>
</methods>

<methods>
<class-id>XSL.CopyOfCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	expression := self readSelectPattern: 'select'</body>
</methods>

<methods>
<class-id>XSL.CopyOfCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'copy-of'</body>
</methods>

<methods>
<class-id>XSL.VariableDefinition</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	aDB addVariable: self</body>
</methods>

<methods>
<class-id>XSL.VariableDefinition</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| val |
	val := self valueAsVariableIn: aNodeContext.
	aNodeContext variables at: name put: val</body>
</methods>

<methods>
<class-id>XSL.VariableDefinition</class-id> <category>accessing</category>

<body package="XSL" selector="expression">expression

	self testPatternInitialized.
	^expression</body>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	^self</body>
</methods>

<methods>
<class-id>XSL.VariableDefinition</class-id> <category>initialize</category>

<body package="XSL" selector="normalize">normalize

	super normalize.
	self parent defineVariable: self</body>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	name := self readAttribute: 'name'.
	expression := self readSelectPattern: 'select' default: [].
	(expression notNil and: [self children isEmpty not])
		ifTrue: [self error: 'A parameter cannot have both content and a select attribute'].</body>
</methods>

<methods>
<class-id>XSL.VariableDefinition</class-id> <category>testing</category>

<body package="XSL" selector="isStylesheetEntry">isStylesheetEntry

	^true</body>
</methods>

<methods>
<class-id>XSL.VariableDefinition class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'variable'</body>
</methods>

<methods>
<class-id>XSL.ChooseWhenCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	testPattern := self readSelectPattern: 'test'</body>
</methods>

<methods>
<class-id>XSL.ChooseWhenCommand</class-id> <category>accessing</category>

<body package="XSL" selector="testPattern">testPattern

	self testPatternInitialized.
	^testPattern</body>
</methods>

<methods>
<class-id>XSL.ChooseWhenCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	self shouldNotImplement</body>
</methods>

<methods>
<class-id>XSL.ChooseWhenCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'when'</body>
</methods>

<methods>
<class-id>XSL.CounterResetCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	super testPatternInitialized.
	name := self readAttribute: 'name'.
	userData := true.</body>
</methods>

<methods>
<class-id>XSL.CounterResetCommand</class-id> <category>accessing</category>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>
</methods>

<methods>
<class-id>XSL.CounterResetCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	aProxy resetCounter: self name</body>
</methods>

<methods>
<class-id>XSL.CounterResetCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'counter-reset'</body>
</methods>

<methods>
<class-id>XSL.OutputCommand</class-id> <category>accessing</category>

<body package="XSL" selector="method">method

	method == nil
		ifTrue: [method := self readAttribute: 'method' default: [#auto]].
	^method</body>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	elements == nil ifFalse: [self error: 'Output declarations should not have contents']</body>
</methods>

<methods>
<class-id>XSL.OutputCommand</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	aDB setOutput: self</body>
</methods>

<methods>
<class-id>XSL.OutputCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'output'</body>
</methods>

<methods>
<class-id>XSL.ApplyTemplatesCommand</class-id> <category>accessing</category>

<body package="XSL" selector="addSortBlock:">addSortBlock: aSortCommand

	sortList == nil ifTrue: [sortList := #()].
	sortList := sortList copyWith: aSortCommand</body>

<body package="XSL" selector="mode">mode

	self testPatternInitialized.
	^mode</body>

<body package="XSL" selector="selectPattern">selectPattern

	self testPatternInitialized.
	^selectPattern</body>

<body package="XSL" selector="sortList">sortList

	^sortList</body>
</methods>

<methods>
<class-id>XSL.ApplyTemplatesCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	selectPattern := self readSelectPattern: 'select' default: [nil].
	mode := self readAttribute: 'mode' default: [nil]</body>
</methods>

<methods>
<class-id>XSL.ApplyTemplatesCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| list rule arguments argList listCopy |
	self selectPattern == nil
		ifTrue: [list := self xslNodesFrom: aNodeContext]
		ifFalse: [list := self selectAll: aNodeContext withPattern: self selectPattern].
	self sortList == nil
		ifTrue: [list documentOrder; ensureSorted]
		ifFalse:
			[listCopy := list shallowCopy.
			list sort: [:n1 :n2 | self collate: n1 to: n2 within: listCopy]].
	arguments := Dictionary new.
	argList := self xslElements.
	1 to: argList size do: [:i |
		(argList at: i) process: aNodeContext intoArgs: arguments].
	list reset.
	[list atEnd]
		whileFalse:
			[list variables: list variables clone.
			rule := list db ruleMatching: list next mode: self mode.
			rule == nil ifFalse: [rule process: list into: aProxy arguments: arguments]]</body>
</methods>

<methods>
<class-id>XSL.ApplyTemplatesCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'apply-templates'</body>
</methods>

<methods>
<class-id>XSL.SAXTextWriter</class-id> <category>content handler</category>

<body package="XSL" selector="characters:from:to:">characters: aString from: start to: stop

	output next: stop+1-start putAll: aString startingAt: start</body>

<body package="XSL" selector="endElement:localName:qName:">endElement: namespaceURI localName: localName qName: name

	^self</body>

<body package="XSL" selector="startElement:localName:qName:attributes:">startElement: namespaceURI localName: localName qName: name attributes: attributes

	^self</body>
</methods>

<methods>
<class-id>XSL.Import</class-id> <category>accessing</category>

<body package="XSL" selector="href">href

	self testPatternInitialized.
	^href</body>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	| idx |
	elements == nil ifFalse: [self error: 'Imports should not have contents.'].
	(self parent isKindOf: RuleSet)
		ifFalse: [self error: self tag asString, ' can only be used at the top level'].
	idx := self parent children indexOf: self.
	(idx = 1 or: [(self parent children at: idx-1) class == self class])
		ifFalse: [self error: 'All imports must come first in the stylesheet'].</body>
</methods>

<methods>
<class-id>XSL.Import</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	href := self readAttribute: 'href'.</body>
</methods>

<methods>
<class-id>XSL.Import</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	| uri |
	uri := aDB uriStack last resolveRelativePath: self href.
	aDB uriStack addLast: uri.
	aDB readStream: uri resource topLevel: false.
	aDB uriStack removeLast.
	aDB raiseImportance</body>
</methods>

<methods>
<class-id>XSL.Import class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'import'</body>
</methods>

<methods>
<class-id>XSL.ParamDefinition</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	aDB addVariable: self</body>
</methods>

<methods>
<class-id>XSL.ParamDefinition</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	self shouldNotImplement</body>

<body package="XSL" selector="process:into:takeArgumentsFrom:">process: aNodeContext into: aProxy takeArgumentsFrom: arguments

	| val |
	val := arguments at: self name ifAbsent: [].
	val == nil
		ifTrue: [val := self valueAsVariableIn: aNodeContext].
	aNodeContext variables at: self name put: val.</body>
</methods>

<methods>
<class-id>XSL.ParamDefinition</class-id> <category>accessing</category>

<body package="XSL" selector="expression">expression

	self testPatternInitialized.
	^expression</body>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	^self</body>
</methods>

<methods>
<class-id>XSL.ParamDefinition</class-id> <category>initialize</category>

<body package="XSL" selector="normalize">normalize

	super normalize.
	self parent defineParameter: self</body>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	name := self readAttribute: 'name'.
	expression := self readSelectPattern: 'select' default: [].
	(expression notNil and: [self children isEmpty not])
		ifTrue: [self error: 'A parameter cannot have both content and a select attribute'].</body>
</methods>

<methods>
<class-id>XSL.ParamDefinition</class-id> <category>testing</category>

<body package="XSL" selector="isStylesheetEntry">isStylesheetEntry

	^true</body>
</methods>

<methods>
<class-id>XSL.ParamDefinition class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'param'</body>
</methods>

<methods>
<class-id>XSL.SortCommand</class-id> <category>accessing</category>

<body package="XSL" selector="caseOrder">caseOrder

	self testPatternInitialized.
	^caseOrder</body>

<body package="XSL" selector="dataType">dataType

	self testPatternInitialized.
	^dataType</body>

<body package="XSL" selector="lang">lang

	self testPatternInitialized.
	^lang</body>

<body package="XSL" selector="order">order

	self testPatternInitialized.
	^order</body>

<body package="XSL" selector="selectPattern">selectPattern

	self testPatternInitialized.
	^selectPattern</body>
</methods>

<methods>
<class-id>XSL.SortCommand</class-id> <category>initialize</category>

<body package="XSL" selector="normalize">normalize

	super normalize.
	(self parent respondsTo: #addSortBlock:)
		ifFalse: [self error: self tag asString, ' can''t be a child element of ', self parent tag asString].
	self parent addSortBlock: self</body>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	selectPattern := self readSelectPattern: 'select' default: ['.'].
	order := self readAttribute: 'order' default: ['ascending'].
	lang := self readAttribute: 'lang' default: [nil].
	dataType := self readAttribute: 'data-type' default: ['text'].
	caseOrder := self readAttribute: 'case-order' default: ['upper-first'].</body>
</methods>

<methods>
<class-id>XSL.SortCommand</class-id> <category>processing</category>

<body package="XSL" selector="collate:to:within:">collate: node1 to: node2 within: aNodeContext

	| v1 v2 result collate |
	collate := aNodeContext.
	collate indexForNode: node1.
	v1 := self selectPattern xpathValueIn: collate.
	collate indexForNode: node2.
	v2 := self selectPattern xpathValueIn: collate.
	dataType = 'number'
		ifTrue: [result := (v1 xpathAsNumber - v2 xpathAsNumber) sign]
		ifFalse: [result := Locale current collationPolicy collate: v1 xpathAsString to: v2 xpathAsString].
	order = 'descending' ifTrue: [result := result negated].
	^result</body>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	"Do nothing. I am only present as a modifier on for-each or apply-templates"
	^self</body>

<body package="XSL" selector="process:intoArgs:">process: aNodeContext intoArgs: aDictionary

	"Do nothing. I am only present as a modifier on for-each or apply-templates.
	For compatibility with &lt;with-parm&gt;"
	^self</body>
</methods>

<methods>
<class-id>XSL.SortCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'sort'</body>
</methods>

<methods>
<class-id>XSL.ChooseCommand</class-id> <category>private</category>

<body package="XSL" selector="elements:">elements: aList

	| newList hasOtherwise |
	newList := aList select: [:i | i isContent and: [i isBlankText not]].
	hasOtherwise := false.
	newList do: [:elm |
		elm class = ChooseOtherwiseCommand
			ifTrue:
				[hasOtherwise ifTrue: [self error: 'xsl:choose with multiple xsl:otherwise commands'].
				hasOtherwise := true]
			ifFalse: [elm class = ChooseWhenCommand
				ifFalse: [self error: 'xsl:choose can only contain xsl:when and xsl:otherwise']]].
	super elements: newList</body>
</methods>

<methods>
<class-id>XSL.ChooseCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| alt match list |
	alt := match := nil.
	elements do: [:elm |
		elm class == ChooseOtherwiseCommand
			ifTrue: [alt := elm]
			ifFalse: [(match == nil and: [(elm testPattern xpathValueIn: aNodeContext) xpathAsBoolean])
				ifTrue: [match := elm]]].
	match == nil ifTrue: [match := alt].
	match notNil
		ifTrue:
			[list := match xslElements.
			1 to: list size do: [:i || elm |
				elm := list at: i.
				elm process: aNodeContext into: aProxy]]</body>
</methods>

<methods>
<class-id>XSL.ChooseCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'choose'</body>
</methods>

<methods>
<class-id>XSL.Include</class-id> <category>accessing</category>

<body package="XSL" selector="href">href

	self testPatternInitialized.
	^href</body>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	elements == nil ifFalse: [self error: 'Includes should not have contents.'].
	(self parent isKindOf: RuleSet)
		ifFalse: [self error: self tag asString, ' can only be used at the top level'].</body>
</methods>

<methods>
<class-id>XSL.Include</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	href := self readAttribute: 'href'.</body>
</methods>

<methods>
<class-id>XSL.Include</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	| uri save |
	save := aDB importance.
	aDB importance: save copy.
	uri := aDB uriStack last resolveRelativePath: self href.
	aDB uriStack addLast: uri.
	aDB readStream: uri resource topLevel: false.
	aDB uriStack removeLast.
	aDB replaceImportance: save</body>
</methods>

<methods>
<class-id>XSL.Include class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'include'</body>
</methods>

<methods>
<class-id>XSL.WithParamCommand</class-id> <category>accessing</category>

<body package="XSL" selector="expression">expression

	self testPatternInitialized.
	^expression</body>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>
</methods>

<methods>
<class-id>XSL.WithParamCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	name := self readAttribute: 'name'.
	expression := self readSelectPattern: 'select' default: [].
	(expression notNil and: [self children isEmpty not])
		ifTrue: [self error: 'A parameter cannot have both content and a select attribute'].</body>
</methods>

<methods>
<class-id>XSL.WithParamCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	self shouldNotImplement</body>

<body package="XSL" selector="process:intoArgs:">process: aNodeContext intoArgs: aDictionary

	| val |
	val := self valueAsVariableIn: aNodeContext.
	aDictionary at: self name put: val.</body>
</methods>

<methods>
<class-id>XSL.WithParamCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'with-param'</body>
</methods>

<methods>
<class-id>XSL.ChainedDictionary</class-id> <category>accessing</category>

<body package="XSL" selector="associationAt:ifAbsent:">associationAt: anIndex ifAbsent: aBlock

	^super associationAt: anIndex ifAbsent: [parent associationAt: anIndex ifAbsent: aBlock]</body>

<body package="XSL" selector="at:ifAbsent:">at: anIndex ifAbsent: aBlock

	^super at: anIndex ifAbsent: [parent at: anIndex ifAbsent: aBlock]</body>

<body package="XSL" selector="clone">clone

	^self class new parent: parent</body>

<body package="XSL" selector="parent">parent

	^parent</body>

<body package="XSL" selector="parent:">parent: aParent

	aParent == nil ifTrue: [self halt].
	parent := aParent</body>

<body package="XSL" selector="size">size

	| s |
	s := Set new.
	self keysAndValuesDo: [:k :v |
		s add: k].
	^s size</body>
</methods>

<methods>
<class-id>XSL.ChainedDictionary</class-id> <category>dictionary enumerating</category>

<body package="XSL" selector="associationsDo:">associationsDo: aBlock 
	"Evaluate aBlock for each of the receiver's key/value associations."

	self keysAndValuesDo: [:k :v |
		aBlock value: k -&gt; v]</body>
</methods>

<methods>
<class-id>XSL.ChainedDictionary</class-id> <category>dictionary testing</category>

<body package="XSL" selector="includesKey:">includesKey: key 
	"Answer whether the receiver has a key equal to the argument, key."

	^(super includesKey: key) or: [parent includesKey: key]</body>
</methods>

<methods>
<class-id>XSL.ChainedDictionary</class-id> <category>enumerating</category>

<body package="XSL" selector="do:">do: aBlock 
	"Evaluate aBlock with each of the receiver's elements as the 
	argument."

	self keysDo: [:k | aBlock value: (self at: k)]</body>

<body package="XSL" selector="keysAndValuesDo:">keysAndValuesDo: aBlock 
	"Evaluate aBlock with each of the receiver's key/value pairs as the 
	arguments."

	| keys |
	keys := Set new.
	super keysAndValuesDo: [:k :v | keys add: k].
	parent keysAndValuesDo: [:k :v | keys add: k].
	keys do: [:k |
		aBlock value: k value: (self at: k)].</body>
</methods>

<methods>
<class-id>XSL.ChainedDictionary</class-id> <category>private</category>

<body package="XSL" selector="changeCapacityTo:">changeCapacityTo: newCapacity

	| newSelf |
	newSelf := self copyEmpty: newCapacity.
	newSelf parent: parent.
	super associationsDo: [:each | newSelf noCheckAdd: each].
	self become: newSelf.</body>
</methods>

<methods>
<class-id>XSL.AttributeSet</class-id> <category>accessing</category>

<body package="XSL" selector="allAttributesFrom:">allAttributesFrom: aDB

	| all |
	all := Dictionary new.
	useAttrs do: [:setName |
		(aDB attributesForSet: setName)
			do: [:attr | all at: attr name put: attr]].
	self xslElements do: [:attr |
		attr class == AttributeCommand ifFalse: [self error: 'Attribute sets only contain attributes'].
		all at: attr name put: attr].
	^all asOrderedCollection</body>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>
</methods>

<methods>
<class-id>XSL.AttributeSet</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	aDB addAttributeSet: self</body>
</methods>

<methods>
<class-id>XSL.AttributeSet</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| list |
	list := self xslElements.
	1 to: list size do: [:i || elm |
		elm := list at: i.
		elm process: aNodeContext into: aProxy].</body>
</methods>

<methods>
<class-id>XSL.AttributeSet</class-id> <category>initialize</category>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	elements := self children reject: [:i | i isBlankText].
	elements do: [:elm |
		elm generatesAttributes
			ifFalse: [self error: 'xsl:attribute-set can contain only xsl:attribute and xsl:use']]</body>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	name := self readAttribute: 'name'.
	useAttrs := self readTagList: 'use-attribute-sets' default: [#()].</body>
</methods>

<methods>
<class-id>XSL.AttributeSet class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'attribute-set'</body>
</methods>

<methods>
<class-id>XSL.CountingProxy</class-id> <category>building</category>

<body package="XSL" selector="add:">add: element

	nextLink add: element</body>

<body package="XSL" selector="addAttribute:">addAttribute: attribute

	nextLink addAttribute: attribute</body>
</methods>

<methods>
<class-id>XSL.SAXHtmlWriter</class-id> <category>content handler</category>

<body package="XSL" selector="endElement:localName:qName:">endElement: namespaceURI localName: localName qName: name

	namespaceURI isEmpty
		ifFalse: [^super endElement: namespaceURI
				localName: localName
				qName: name].
	hasOpenTag
		ifTrue: [(self htmlSpecialEmptyTags includes: name asLowercase)
			ifTrue: [output nextPutAll: '&gt;']
			ifFalse: [output nextPutAll: '/&gt;']]
		ifFalse: [output nextPutAll: '&lt;/', name asLowercase, '&gt;'].
	hasOpenTag := false.</body>

<body package="XSL" selector="startElement:localName:qName:attributes:">startElement: namespaceURI localName: localName qName: name attributes: attributes

	namespaceURI isEmpty
		ifFalse: [^super startElement: namespaceURI
				localName: localName
				qName: name
				attributes: attributes].
	self closeOpenTag.
	output nextPutAll: '&lt;'.
	output nextPutAll: name asLowercase.
	(self sort: attributes) do: [:att |
		output space.
		output nextPutAll: att tag asString asLowercase.
		(self isBoolean: att in: name)
			ifFalse:
				[output nextPutAll: '="'.
				1 to: att value size do: [:i || ch mapped |
					ch := att value at: i.
					mapped := attrMap at: ch ifAbsent: [nil].
					mapped == nil
						ifTrue: [output nextPut: ch]
						ifFalse: [output nextPutAll: mapped]]].
		output nextPutAll: '"'].
	hasOpenTag := true.
	name asLowercase = 'head'
		ifTrue:
			[| atts |
			atts := OrderedCollection new.
			atts add: (Attribute new
				tag: (NodeTag new qualifier: '' ns: '' type: 'http-equiv');
				value: 'Content-Type').
			atts add: (Attribute new
				tag: (NodeTag new qualifier: '' ns: '' type: 'content');
				value: 'text/html; charset=utf-8').
			atts := atts asArray.
			self startElement: '' localName: 'meta' qName: 'meta' attributes: atts.
			self endElement: '' localName: 'meta' qName: 'meta'].</body>
</methods>

<methods>
<class-id>XSL.SAXHtmlWriter</class-id> <category>accessing</category>

<body package="XSL" selector="htmlSpecialEmptyTags">htmlSpecialEmptyTags

	htmlSpecialEmptyTags == nil
		ifTrue: [htmlSpecialEmptyTags := #('area' 'base' 'basefont' 'br' 'col' 'frame' 'hr' 'img' 'input' 'isindex' 'link' 'meta' 'param')].
	^htmlSpecialEmptyTags</body>

<body package="XSL" selector="htmlSpecialEmptyTags:">htmlSpecialEmptyTags: aList

	htmlSpecialEmptyTags := aList</body>
</methods>

<methods>
<class-id>XSL.SAXHtmlWriter</class-id> <category>testing</category>

<body package="XSL" selector="isBoolean:in:">isBoolean: attribute in: elementTag

	^false</body>
</methods>

<methods>
<class-id>XSL.NumberCommand</class-id> <category>accessing</category>

<body package="XSL" selector="countFor:">countFor: aNode

	aNode isElement ifFalse: [self halt: 'Counting things other than elements is not supported yet'].
	self testPatternInitialized.
	^count == nil
		ifTrue: [XPathChildNode new axisName: 'child'; baseTest: (XPathTaggedNodeTest new namespace: aNode tag namespace; type: aNode tag type)]
		ifFalse: [count]</body>

<body package="XSL" selector="from">from

	self testPatternInitialized.
	^from</body>

<body package="XSL" selector="level">level

	self testPatternInitialized.
	^level</body>
</methods>

<methods>
<class-id>XSL.NumberCommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	super testPatternInitialized.
	level := (self readAttribute: 'level' default: [#single]) asSymbol.
	count := self readMatchPattern: 'count' default: [nil].
	from := self readMatchPattern: 'from' default: [nil].
	userData := true.</body>
</methods>

<methods>
<class-id>XSL.NumberCommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	self level == #single
		ifTrue: [^self processSingle: aNodeContext into: aProxy].
	self level == #multi
		ifTrue: [^self processMulti: aNodeContext into: aProxy].
	self level == #any
		ifTrue: [^self processAny: aNodeContext into: aProxy].
	^self error: 'Unsupported numbering mode'</body>

<body package="XSL" selector="processAny:into:">processAny: aNodeContext into: aProxy

	| n countP |
	n := 0.
	countP := self countFor: aNodeContext node.
	NodeIterator new
		node: aNodeContext node;
		reverseDo: [:nd | (countP match: (aNodeContext copy add: nd; index: 1)) ifTrue: [n := n+1]]
			until: [:nd | self from notNil and: [self from match: (aNodeContext copy add: nd; index: 1)]].
	aProxy addNode: (Text new text: (self format: (Array with: n) for: aNodeContext))</body>

<body package="XSL" selector="processMulti:into:">processMulti: aNodeContext into: aProxy

	| allNodes n counts countP sibSelect cnt sibs |
	countP := self countFor: aNodeContext node.
	allNodes := aNodeContext copy.
	n := aNodeContext node.
	[n == nil or: [self from notNil and: [self from match: n]]] whileFalse:
		[allNodes add: n.
		n := n parent].
	allNodes := allNodes selectMatch: countP.
	allNodes documentOrder; index: 1.
	sibSelect := XPathParser parse: '../node()' as: #expression.
	counts := OrderedCollection new.
	allNodes reset.
	[allNodes atEnd] whileFalse:
		[allNodes next.
		cnt := 1.
		sibs := sibSelect xpathValueIn: allNodes.
		sibs reset; next.
		[sibs node == allNodes node]
			whileFalse:
				[(countP match: sibs) ifTrue: [cnt := cnt+1].
				sibs next].
		counts add: cnt].
	aProxy addNode: (Text new text: (self format: counts asArray for: aNodeContext))</body>

<body package="XSL" selector="processSingle:into:">processSingle: aNodeContext into: aProxy

	| allNodes n cnt countP sibSelect sibs |
	countP := self countFor: aNodeContext node.
	allNodes := aNodeContext copy.
	n := aNodeContext node.
	[n == nil or: [self from notNil and: [self from match: n]]] whileFalse:
		[allNodes add: n.
		n := n parent].
	allNodes := allNodes selectMatch: countP.
	allNodes size = 0 ifTrue: [^self].
	allNodes inverseDocumentOrder; index: 1.
	sibSelect := XPathParser parse: '../node()' as: #expression.
	sibs := sibSelect xpathValueIn: allNodes.
	sibs reset; next.
	cnt := 1.
	[sibs node == allNodes node]
		whileFalse:
			[(countP match: sibs) ifTrue: [cnt := cnt+1].
			sibs next].
	aProxy addNode: (Text new text: (self format: (Array with: cnt) for: aNodeContext))</body>
</methods>

<methods>
<class-id>XSL.NumberCommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'number'</body>
</methods>

<methods>
<class-id>XSL.PICommand</class-id> <category>initialize</category>

<body package="XSL" selector="testPatternInitialized">testPatternInitialized

	userData ifTrue: [^self].
	userData := true.
	name := self readTag: 'name'</body>
</methods>

<methods>
<class-id>XSL.PICommand</class-id> <category>accessing</category>

<body package="XSL" selector="name">name

	self testPatternInitialized.
	^name</body>
</methods>

<methods>
<class-id>XSL.PICommand</class-id> <category>processing</category>

<body package="XSL" selector="process:into:">process: aNodeContext into: aProxy

	| oc str |
	oc := aProxy childProxy.
	self xslElements do: [:elm |
		elm process: aNodeContext into: oc].
	oc attributes isEmpty ifFalse: [self error: 'Comments do not support attributes'].
	str := (String new: 128) writeStream.
	oc children do: [:nd |
		nd isText ifFalse: [self error: 'Comments can only contain text, not elements, pi''s, or other comments'].
		str nextPutAll: nd characterData].
	str := str contents.
	str := str copyReplaceAll: '?&gt;' with: '? &gt;'.
	aProxy addNode: (PI new name: self name text: str)</body>
</methods>

<methods>
<class-id>XSL.PICommand class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'pi'</body>
</methods>

<methods>
<class-id>XSL.DecimalFormat</class-id> <category>loading</category>

<body package="XSL" selector="addToRuleDB:">addToRuleDB: aDB
	"This is only understood by a small subset of commands."

	self notYetImplemented</body>
</methods>

<methods>
<class-id>XSL.DecimalFormat</class-id> <category>accessing</category>

<body package="XSL" selector="purgeUnimportant">purgeUnimportant

	elements == nil ifFalse: [self error: 'Format declarations should not have contents']</body>
</methods>

<methods>
<class-id>XSL.DecimalFormat class</class-id> <category>accessing</category>

<body package="XSL" selector="tag">tag

	^'decimal-format'</body>
</methods>

<initialize>
<class-id>XSL.XSLCommand</class-id>
</initialize>

<do-it>"Imported Classes:"</do-it>

<do-it>self error: 'Attempting to file-in parcel imports.  Choose terminate or close'</do-it>

<class>
<name>Object</name>
<environment>Core</environment>
<super></super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>Kernel-Objects</category>
<attributes>
<package>Kernel-Objects</package>
</attributes>
</class>

<class>
<name>Link</name>
<environment>Core</environment>
<super>Core.Object</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>nextLink </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>Collections-Support</category>
<attributes>
<package>Collections-Support</package>
</attributes>
</class>

<class>
<name>Array</name>
<environment>Core</environment>
<super>Core.ArrayedCollection</super>
<private>false</private>
<indexed-type>objects</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>Collections-Arrayed</category>
<attributes>
<package>Collections-Arrayed</package>
</attributes>
</class>

<class>
<name>Dictionary</name>
<environment>Core</environment>
<super>Core.Set</super>
<private>false</private>
<indexed-type>objects</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>Collections-Unordered</category>
<attributes>
<package>Collections-Unordered</package>
</attributes>
</class>

<class>
<name>XPathNodeContext</name>
<environment>XML</environment>
<super>Core.Object</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>documentOrder nodes index node baseNode variables </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XPath</category>
<attributes>
<package>XPath</package>
</attributes>
</class>

<class>
<name>NodeBuilder</name>
<environment>XML</environment>
<super>XML.XMLNodeBuilder</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-Parsing</category>
<attributes>
<package>XML</package>
</attributes>
</class>

<class>
<name>Element</name>
<environment>XML</environment>
<super>XML.Node</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>tag attributes namespaces elements definition </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-Nodes</category>
<attributes>
<package>XML</package>
</attributes>
</class>

<class>
<name>Text</name>
<environment>XML</environment>
<super>XML.Node</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>text stripped </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-Nodes</category>
<attributes>
<package>XML</package>
</attributes>
</class>

<class>
<name>PI</name>
<environment>XML</environment>
<super>XML.Node</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name text </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-Nodes</category>
<attributes>
<package>XML</package>
</attributes>
</class>

<class>
<name>SAXWriter</name>
<environment>XML</environment>
<super>XML.SAXDriver</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>output textMap attrMap hasOpenTag normalizeText notations newNamespaces </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>XML-SAX</category>
<attributes>
<package>XML</package>
</attributes>
</class>

</st-source>
