xml-toolkit 1.0.60 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,8 @@ const XMLSchemaXml = require ('./XMLSchemaXml.js')
8
8
  const XMLSchemaBuiltIn = require ('./XMLSchemaBuiltIn.js')
9
9
  const XMLMarshaller = require ('./XMLMarshaller.js')
10
10
 
11
- const {XSSimpleType} = require ('./XSSimpleType.js')
11
+ const XSAnyType = require ('./XSAnyType.js')
12
+ const {XSSimpleType} = require ('./simple/XSSimpleType.js')
12
13
 
13
14
  const IDX = Symbol ('_index')
14
15
 
@@ -32,6 +33,12 @@ const XMLSchemata = class extends Map {
32
33
  this.addFile (fn)
33
34
 
34
35
  }
36
+
37
+ getDebugQName (localName, namespaceURI) {
38
+
39
+ return namespaceURI ? `{${namespaceURI}}${localName}` : localName
40
+
41
+ }
35
42
 
36
43
  register (name, targetNamespace) {
37
44
 
@@ -51,10 +58,20 @@ const XMLSchemata = class extends Map {
51
58
 
52
59
  if (node.localName === 'simpleType' && !node._xsSimpleType) node._xsSimpleType = new (schema.getSimpleTypeClass (node)) (this)
53
60
 
61
+ if (!('targetNamespace' in node)) node.targetNamespace = namespaceURI
62
+
54
63
  return node
55
64
 
56
65
  }
57
66
 
67
+ getAnyType (node) {
68
+
69
+ if ('_xsAnyType' in node) return node._xsAnyType
70
+
71
+ return node._xsAnyType = new XSAnyType (this, node)
72
+
73
+ }
74
+
58
75
  getSimpleType (node) {
59
76
 
60
77
  if ('_xsSimpleType' in node) return node._xsSimpleType
@@ -65,15 +82,65 @@ const XMLSchemata = class extends Map {
65
82
 
66
83
  getSimpleTypeClass (node) {
67
84
 
68
- if (node) for (const {localName, namespaceURI, attributes: {base}, children} of node.children)
69
-
70
- if (localName === 'restriction' && namespaceURI === XMLSchema.namespaceURI)
85
+ if (node) for (const {localName, attributes: {base}, children} of node.children) switch (localName) {
86
+
87
+ case 'restriction': return this.getType (base)._xsSimpleType.restrict (children)
88
+
89
+ case 'union': return class {
90
+
91
+ constructor (xs) {
92
+
93
+ this.xs = xs
94
+
95
+ this.nodes = children
96
+
97
+ }
98
+
99
+ stringify (v) {
100
+
101
+ const messages = []; for (const node of this.nodes) {
102
+
103
+ try {
104
+
105
+ return this.xs.getSimpleType (node).stringify (v)
106
+
107
+ }
108
+ catch (err) {
109
+
110
+ messages.push (err.message)
111
+
112
+ }
71
113
 
72
- return this.getType (base)._xsSimpleType.restrict (children.map (
114
+ }
115
+
116
+ throw Error (messages.join ('; '))
73
117
 
74
- ({localName, attributes: {value}}) => ({name: localName, value})
118
+ }
75
119
 
76
- ))
120
+ validateScalar (v) {
121
+
122
+ const messages = []; for (const node of this.nodes) {
123
+
124
+ try {
125
+
126
+ return this.xs.getSimpleType (node).validateScalar (v)
127
+
128
+ }
129
+ catch (err) {
130
+
131
+ messages.push (err.message)
132
+
133
+ }
134
+
135
+ }
136
+
137
+ throw Error (messages.join ('; '))
138
+
139
+ }
140
+
141
+ }
142
+
143
+ }
77
144
 
78
145
  return XSSimpleType
79
146
 
@@ -98,10 +165,26 @@ const XMLSchemata = class extends Map {
98
165
  getByReference (ref) {
99
166
 
100
167
  const [localName, namespaceURI] = ref
101
-
102
- const s = this.get (namespaceURI); if (s == null) throw new Error ('Unknown namespace: ' + namespaceURI)
103
-
104
- return s.get (localName)
168
+
169
+ return this.getSchema (namespaceURI).get (localName)
170
+
171
+ }
172
+
173
+ getSchema (namespaceURI) {
174
+
175
+ if (!this.has (namespaceURI)) throw new Error ('Unknown namespace: ' + namespaceURI)
176
+
177
+ return this.get (namespaceURI)
178
+
179
+ }
180
+
181
+ getTypeDefinition (node) {
182
+
183
+ // while (node.attributes.ref) node = this.getByReference (node.attributes.ref)
184
+
185
+ if (node.attributes.type) return this.getType (node.attributes.type)
186
+
187
+ return node.children.find (i => i.localName.endsWith ('Type'))
105
188
 
106
189
  }
107
190
 
@@ -0,0 +1,98 @@
1
+ const Occurable = require ('./validation/Occurable')
2
+
3
+ module.exports = class {
4
+
5
+ #isAnyAttributeAllowed = false
6
+ #isExtended = false
7
+ #parent = null
8
+
9
+ get isAnyAttributeAllowed () {
10
+
11
+ return this.#isAnyAttributeAllowed
12
+
13
+ }
14
+
15
+ constructor (xs, node) {
16
+
17
+ this.xs = xs
18
+ this.node = node
19
+
20
+ this.attributes = new Map ()
21
+ this.elements = []
22
+
23
+ this.scan (node)
24
+
25
+ if (this.#parent === null) return
26
+
27
+ if (this.#isExtended) this.extend (); else this.restrict ()
28
+
29
+ }
30
+
31
+ extend () {
32
+
33
+ this.attributes = new Map ([
34
+ ...this.#parent.attributes,
35
+ ...this.attributes
36
+ ])
37
+
38
+ this.elements = this.#parent.elements.concat (this.elements)
39
+
40
+ this.content = new Occurable ([this.#parent.content, this.content])
41
+
42
+ }
43
+
44
+ restrict () {
45
+
46
+ this.attributes = new Map ([
47
+ ...this.#parent.attributes,
48
+ ...this.attributes
49
+ ])
50
+
51
+ }
52
+
53
+ asSimpleType () {
54
+
55
+ return this.xs.getSimpleType (this.node)
56
+
57
+ }
58
+
59
+ get debugQName () {
60
+
61
+ const {xs, node} = this
62
+
63
+ return xs.getDebugQName (node.attributes.name, node.targetNamespace)
64
+
65
+ }
66
+
67
+ scan (node) {
68
+
69
+ while (node.attributes.ref) node = this.xs.getByReference (node.attributes.ref)
70
+
71
+ switch (node.localName) {
72
+
73
+ case 'anyAttribute': return this.#isAnyAttributeAllowed = true
74
+
75
+ case 'attribute': return this.attributes.set (node.attributes.name, node)
76
+
77
+ case 'any':
78
+ case 'element':
79
+ return this.elements.push (node)
80
+
81
+ case 'all':
82
+ case 'choice':
83
+ case 'sequence':
84
+ this.content ??= new Occurable (node, this.xs)
85
+ break
86
+
87
+ case 'extension':
88
+ this.#isExtended = true
89
+ case 'restriction':
90
+ this.#parent = this.xs.getAnyType (this.xs.getType (node.attributes.base))
91
+
92
+ }
93
+
94
+ for (const child of node.children) this.scan (child)
95
+
96
+ }
97
+
98
+ }
@@ -1,6 +1,6 @@
1
1
  const os = require ('os')
2
2
  const stringEscape = require ('string-escape-map')
3
- const SAXEvent = require ('./SAXEvent.js')
3
+ const SAXEvent = require ('../SAXEvent.js')
4
4
 
5
5
  const CH_QQ = '"'.charCodeAt (0)
6
6
  const CH_GT = '>'.charCodeAt (0)
@@ -19,7 +19,7 @@ const ESC = [
19
19
 
20
20
  const isSafeNonNegative = value => Number.isSafeInteger (value) && value >= 0
21
21
 
22
- const XMLPrinter = class {
22
+ module.exports = class {
23
23
 
24
24
  constructor (o = {}) {
25
25
 
@@ -85,7 +85,6 @@ const XMLPrinter = class {
85
85
 
86
86
  reset () {
87
87
 
88
- this.text = ''
89
88
  this.stack = []
90
89
  this.isOpening = false
91
90
 
@@ -97,15 +96,7 @@ const XMLPrinter = class {
97
96
 
98
97
  newLine (delta = 0) {
99
98
 
100
- this.text += `${this.EOL}${this.space.repeat (this.level + this.stack.length + delta)}`
101
-
102
- }
103
-
104
- get lastCharCode () {
105
-
106
- const {text} = this
107
-
108
- return text.charCodeAt (text.length - 1)
99
+ this.write (`${this.EOL}${this.space.repeat (this.level + this.stack.length + delta)}`)
109
100
 
110
101
  }
111
102
 
@@ -113,12 +104,12 @@ const XMLPrinter = class {
113
104
 
114
105
  if (this.stack.length !== 0) {
115
106
  if (this.attrSpace && this.lastCharCode === CH_QQ) this.newLine (-1)
116
- if (this.isOpening) this.text += `>`
107
+ if (this.isOpening) this.write (`>`)
117
108
  }
118
109
 
119
- if (this.space && this.text) this.newLine ()
110
+ if (this.space && !this.isVirgin) this.newLine ()
120
111
 
121
- this.text += `<${name}`
112
+ this.write (`<${name}`)
122
113
  this.stack.push (name)
123
114
 
124
115
  this.isOpening = true
@@ -139,16 +130,16 @@ const XMLPrinter = class {
139
130
 
140
131
  this.newLine (-1)
141
132
 
142
- this.text += this.attrSpace
133
+ this.write (this.attrSpace)
143
134
 
144
135
  }
145
136
  else {
146
137
 
147
- this.text += ' '
138
+ this.write (' ')
148
139
 
149
140
  }
150
141
 
151
- this.text += `${name}="${this.ESC_ATTR.escape (value)}"`
142
+ this.write (`${name}="${this.ESC_ATTR.escape (value)}"`)
152
143
 
153
144
  return this
154
145
 
@@ -170,11 +161,11 @@ const XMLPrinter = class {
170
161
 
171
162
  if (this.isOpening) {
172
163
  if (this.attrSpace && this.lastCharCode === CH_QQ) this.newLine (-1)
173
- this.text += `>`
164
+ this.write (`>`)
174
165
  this.isOpening = false
175
166
  }
176
167
 
177
- this.text += value
168
+ this.write (value)
178
169
 
179
170
  return this
180
171
 
@@ -186,12 +177,12 @@ const XMLPrinter = class {
186
177
 
187
178
  if (this.isOpening) {
188
179
  if (this.attrSpace && this.lastCharCode === CH_QQ) this.newLine ()
189
- this.text += ` />`
180
+ this.write (` />`)
190
181
  this.isOpening = false
191
182
  }
192
183
  else {
193
184
  if (this.space && this.lastCharCode === CH_GT) this.newLine ()
194
- this.text += `</${name}>`
185
+ this.write (`</${name}>`)
195
186
  }
196
187
 
197
188
  return this
@@ -271,18 +262,16 @@ const XMLPrinter = class {
271
262
 
272
263
  if (this.stack.length !== 0) throw Error ('The document is already started')
273
264
 
274
- this.text += '<?xml version="1.0"'
265
+ this.write ('<?xml version="1.0"')
275
266
 
276
- if (encoding != null) this.text += ` encoding="${encoding}"`
267
+ if (encoding != null) this.write (` encoding="${encoding}"`)
277
268
 
278
- if (standalone != null) this.text += ` standalone="${standalone ? 'yes' : 'no'}"`
269
+ if (standalone != null) this.write (` standalone="${standalone ? 'yes' : 'no'}"`)
279
270
 
280
- this.text += '?>'
271
+ this.write ('?>')
281
272
 
282
273
  return this
283
274
 
284
- }
285
-
286
- }
275
+ }
287
276
 
288
- module.exports = XMLPrinter
277
+ }
@@ -0,0 +1,39 @@
1
+ const XMLPrinter = class extends (require ('./Base.js')) {
2
+
3
+ get destroy () {
4
+
5
+ return err => {throw err}
6
+
7
+ }
8
+
9
+ reset () {
10
+
11
+ this.text = ''
12
+
13
+ return super.reset ()
14
+
15
+ }
16
+
17
+ get lastCharCode () {
18
+
19
+ const {text} = this
20
+
21
+ return text.charCodeAt (text.length - 1)
22
+
23
+ }
24
+
25
+ get isVirgin () {
26
+
27
+ return this.text.length === 0
28
+
29
+ }
30
+
31
+ write (s) {
32
+
33
+ this.text += s
34
+
35
+ }
36
+
37
+ }
38
+
39
+ module.exports = XMLPrinter
@@ -0,0 +1,122 @@
1
+ const {Writable} = require ('node:stream')
2
+
3
+ const XMLStreamPrinter = class extends (require ('./Base.js')) {
4
+
5
+ #inStreams = []
6
+ #isVirgin = true
7
+ #lastCharCode = 0
8
+ #open = true
9
+
10
+ constructor (o) {
11
+
12
+ if (!o || typeof o !== 'object' || !('out' in o)) throw Error (`XMLStreamPrinter requires an .out option`)
13
+ if (!(o.out instanceof Writable)) throw Error (`.out must be Writable, ${typeof o.out} ${o.out} found`)
14
+
15
+ super (o)
16
+
17
+ this.out = o.out
18
+ this.out.on ('drain', () => this.open = true)
19
+
20
+ }
21
+
22
+ get end () {
23
+
24
+ return () => this.out.end ()
25
+
26
+ }
27
+
28
+ get destroy () {
29
+
30
+ return err => this.out.destroy (err)
31
+
32
+ }
33
+
34
+ get inStream () {
35
+
36
+ return this.#inStreams.at (-1)
37
+
38
+ }
39
+
40
+ forEach (stream, onData) {
41
+
42
+ if (this.#inStreams.length !== 0) return this.destroy (Error ('Nested streams not yet supported'))
43
+
44
+ if (!this.#open) stream.pause ()
45
+
46
+ this.#inStreams.push (stream)
47
+
48
+ return new Promise ((ok, fail) => {
49
+
50
+ stream.on ('error', err => {
51
+
52
+ this.destroy (err)
53
+
54
+ fail (err)
55
+
56
+ })
57
+
58
+ stream.on ('end', () => {
59
+
60
+ this.#inStreams.pop ()
61
+
62
+ ok ()
63
+
64
+ })
65
+
66
+ stream.on ('data', data => {
67
+
68
+ try {
69
+
70
+ onData (data)
71
+
72
+ }
73
+ catch (err) {
74
+
75
+ stream.destroy (err)
76
+
77
+ }
78
+
79
+ })
80
+
81
+ })
82
+
83
+ }
84
+
85
+ set open (nowOpen) {
86
+
87
+ const wasOpen = this.#open; if (wasOpen === nowOpen) return
88
+
89
+ this.#open = nowOpen
90
+
91
+ if (!this.inStream) return
92
+
93
+ nowOpen ? this.inStream.resume () : this.inStream.pause ()
94
+
95
+ }
96
+
97
+ get lastCharCode () {
98
+
99
+ return this.#lastCharCode
100
+
101
+ }
102
+
103
+ get isVirgin () {
104
+
105
+ return this.#isVirgin
106
+
107
+ }
108
+
109
+ write (s) {
110
+
111
+ const {length} = s; if (length === 0) return
112
+
113
+ this.#lastCharCode = s.charCodeAt (length - 1)
114
+ this.#isVirgin = false
115
+
116
+ this.open = this.out.write (s)
117
+
118
+ }
119
+
120
+ }
121
+
122
+ module.exports = XMLStreamPrinter