44 forEachObject , isEmpty
55} from "@oozcitak/util"
66import { BaseReader } from "./BaseReader"
7+ import { sanitizeInput } from "../builder/dom"
78
89/**
910 * Parses XML nodes from objects and arrays.
@@ -21,6 +22,12 @@ export class ObjectReader extends BaseReader<ExpandObject> {
2122
2223 const options = this . _builderOptions
2324
25+ // sanitizes input characters
26+ const invalidCharReplacement = options . invalidCharReplacement
27+ const s = function ( str : string ) : string {
28+ return sanitizeInput ( str , invalidCharReplacement )
29+ }
30+
2431 let lastChild : XMLBuilder | null = null
2532
2633 if ( isFunction ( obj ) ) {
@@ -43,56 +50,61 @@ export class ObjectReader extends BaseReader<ExpandObject> {
4350 throw new Error ( "Invalid attribute: " + val . toString ( ) + ". " + ( node as any ) . _debugInfo ( ) )
4451 } else /* if (isMap(val) || isObject(val)) */ {
4552 forEachObject ( val , ( attrKey , attrVal ) => {
46- lastChild = this . attribute ( node , undefined , attrKey , attrVal as string ) || lastChild
53+ lastChild = this . attribute ( node , undefined ,
54+ s ( attrKey ) , s ( attrVal as string ) ) || lastChild
4755 } )
4856 }
4957 } else {
50- lastChild = this . attribute ( node , undefined , key . substr ( options . convert . att . length ) , val ) || lastChild
58+ lastChild = this . attribute ( node , undefined ,
59+ s ( key . substr ( options . convert . att . length ) ) ,
60+ s ( val ) ) || lastChild
5161 }
5262 } else if ( ! options . ignoreConverters && key . indexOf ( options . convert . text ) === 0 ) {
5363 // text node
5464 if ( isMap ( val ) || isObject ( val ) ) {
5565 // if the key is #text expand child nodes under this node to support mixed content
5666 lastChild = this . parse ( node , val )
5767 } else {
58- lastChild = this . text ( node , val ) || lastChild
68+ lastChild = this . text ( node , s ( val ) ) || lastChild
5969 }
6070 } else if ( ! options . ignoreConverters && key . indexOf ( options . convert . cdata ) === 0 ) {
6171 // cdata node
6272 if ( isArray ( val ) || isSet ( val ) ) {
63- forEachArray ( val , item => lastChild = this . cdata ( node , item ) || lastChild , this )
73+ forEachArray ( val , item => lastChild = this . cdata ( node , s ( item ) ) || lastChild , this )
6474 } else {
65- lastChild = this . cdata ( node , val ) || lastChild
75+ lastChild = this . cdata ( node , s ( val ) ) || lastChild
6676 }
6777 } else if ( ! options . ignoreConverters && key . indexOf ( options . convert . comment ) === 0 ) {
6878 // comment node
6979 if ( isArray ( val ) || isSet ( val ) ) {
70- forEachArray ( val , item => lastChild = this . comment ( node , item ) || lastChild , this )
80+ forEachArray ( val , item => lastChild = this . comment ( node , s ( item ) ) || lastChild , this )
7181 } else {
72- lastChild = this . comment ( node , val ) || lastChild
82+ lastChild = this . comment ( node , s ( val ) ) || lastChild
7383 }
7484 } else if ( ! options . ignoreConverters && key . indexOf ( options . convert . ins ) === 0 ) {
7585 // processing instruction
7686 if ( isString ( val ) ) {
7787 const insIndex = val . indexOf ( ' ' )
7888 const insTarget = ( insIndex === - 1 ? val : val . substr ( 0 , insIndex ) )
7989 const insValue = ( insIndex === - 1 ? '' : val . substr ( insIndex + 1 ) )
80- lastChild = this . instruction ( node , insTarget , insValue ) || lastChild
90+ lastChild = this . instruction ( node , s ( insTarget ) , s ( insValue ) ) || lastChild
8191 } else if ( isArray ( val ) || isSet ( val ) ) {
8292 forEachArray ( val , item => {
8393 const insIndex = item . indexOf ( ' ' )
8494 const insTarget = ( insIndex === - 1 ? item : item . substr ( 0 , insIndex ) )
8595 const insValue = ( insIndex === - 1 ? '' : item . substr ( insIndex + 1 ) )
86- lastChild = this . instruction ( node , insTarget , insValue ) || lastChild
96+ lastChild = this . instruction ( node , s ( insTarget ) , s ( insValue ) ) || lastChild
8797 } , this )
8898 } else /* if (isMap(target) || isObject(target)) */ {
89- forEachObject ( val , ( insTarget , insValue ) => lastChild = this . instruction ( node , insTarget , insValue as string ) || lastChild , this )
99+ forEachObject ( val , ( insTarget , insValue ) => lastChild = this . instruction ( node ,
100+ s ( insTarget ) ,
101+ s ( insValue as string ) ) || lastChild , this )
90102 }
91103 } else if ( ( isArray ( val ) || isSet ( val ) ) && isEmpty ( val ) ) {
92104 // skip empty arrays
93105 } else if ( ( isMap ( val ) || isObject ( val ) ) && isEmpty ( val ) ) {
94106 // empty objects produce one node
95- lastChild = this . element ( node , undefined , key ) || lastChild
107+ lastChild = this . element ( node , undefined , s ( key ) ) || lastChild
96108 } else if ( ! options . keepNullNodes && ( val == null ) ) {
97109 // skip null and undefined nodes
98110 } else if ( isArray ( val ) || isSet ( val ) ) {
@@ -115,11 +127,11 @@ export class ObjectReader extends BaseReader<ExpandObject> {
115127 const parent = this . element ( node , undefined , key )
116128 if ( parent ) {
117129 lastChild = parent
118- this . text ( parent , val )
130+ this . text ( parent , s ( val ) )
119131 }
120132 } else {
121133 // leaf element node
122- lastChild = this . element ( node , undefined , key ) || lastChild
134+ lastChild = this . element ( node , undefined , s ( key ) ) || lastChild
123135 }
124136 } , this )
125137 }
0 commit comments