66 DOM_COMMENT_NODE ,
77 DOM_DOCUMENT_FRAGMENT_NODE ,
88 DOM_DOCUMENT_NODE ,
9+ DOM_DOCUMENT_TYPE_NODE ,
910 DOM_ELEMENT_NODE ,
1011 DOM_TEXT_NODE
1112} from '../constants' ;
@@ -14,49 +15,57 @@ import { XNode } from './xnode';
1415import { XDocument } from './xdocument' ;
1516import { XmlOutputOptions } from './xml-output-options' ;
1617
17- // Returns the text value of a node; for nodes without children this
18- // is the nodeValue, for nodes with children this is the concatenation
19- // of the value of all children. Browser-specific optimizations are used by
20- // default; they can be disabled by passing "true" in as the second parameter.
21- export function xmlValue ( node : any , disallowBrowserSpecificOptimization : boolean = false ) {
18+
19+ /**
20+ * Returns the text value of a node; for nodes without children this
21+ * is the nodeValue, for nodes with children this is the concatenation
22+ * of the value of all children. Browser-specific optimizations are used by
23+ * default; they can be disabled by passing "true" in as the second parameter.
24+ * @param node The Node (not exactly a `XNode` here).
25+ * @param disallowBrowserSpecificOptimization A boolean, to avoid browser optimization.
26+ * @returns The XML value as a string.
27+ */
28+ export function xmlValue ( node : any , disallowBrowserSpecificOptimization : boolean = false ) : string {
2229 if ( ! node ) {
2330 return '' ;
2431 }
2532
2633 let ret = '' ;
27- if ( node . nodeType == DOM_TEXT_NODE || node . nodeType == DOM_CDATA_SECTION_NODE ) {
28- ret += node . nodeValue ;
29- } else if ( node . nodeType == DOM_ATTRIBUTE_NODE ) {
30- ret += node . nodeValue ;
31- } else if (
32- node . nodeType == DOM_ELEMENT_NODE ||
33- node . nodeType == DOM_DOCUMENT_NODE ||
34- node . nodeType == DOM_DOCUMENT_FRAGMENT_NODE
35- ) {
36- if ( ! disallowBrowserSpecificOptimization ) {
37- // IE, Safari, Opera, and friends
38- const innerText = node . innerText ;
39- if ( innerText != undefined ) {
40- return innerText ;
41- }
42- // Firefox
43- const textContent = node . textContent ;
44- if ( textContent != undefined ) {
45- return textContent ;
34+ switch ( node . nodeType ) {
35+ case DOM_DOCUMENT_TYPE_NODE :
36+ return `<!DOCTYPE ${ node . nodeValue } >`
37+ case DOM_TEXT_NODE :
38+ case DOM_CDATA_SECTION_NODE :
39+ case DOM_ATTRIBUTE_NODE :
40+ return node . nodeValue ;
41+ case DOM_ELEMENT_NODE :
42+ case DOM_DOCUMENT_NODE :
43+ case DOM_DOCUMENT_FRAGMENT_NODE :
44+ if ( ! disallowBrowserSpecificOptimization ) {
45+ // IE, Safari, Opera, and friends
46+ const innerText = node . innerText ;
47+ if ( innerText != undefined ) {
48+ return innerText ;
49+ }
50+ // Firefox
51+ const textContent = node . textContent ;
52+ if ( textContent != undefined ) {
53+ return textContent ;
54+ }
4655 }
47- }
4856
49- if ( node . transformedChildNodes . length > 0 ) {
50- for ( let i = 0 ; i < node . transformedChildNodes . length ; ++ i ) {
51- ret += xmlValue ( node . transformedChildNodes [ i ] ) ;
52- }
53- } else {
54- for ( let i = 0 ; i < node . childNodes . length ; ++ i ) {
55- ret += xmlValue ( node . childNodes [ i ] ) ;
57+ if ( node . transformedChildNodes . length > 0 ) {
58+ for ( let i = 0 ; i < node . transformedChildNodes . length ; ++ i ) {
59+ ret += xmlValue ( node . transformedChildNodes [ i ] ) ;
60+ }
61+ } else {
62+ for ( let i = 0 ; i < node . childNodes . length ; ++ i ) {
63+ ret += xmlValue ( node . childNodes [ i ] ) ;
64+ }
5665 }
57- }
66+
67+ return ret ;
5868 }
59- return ret ;
6069}
6170
6271// TODO: Give a better name to this.
@@ -98,14 +107,17 @@ export function xmlValue2(node: any, disallowBrowserSpecificOptimization: boolea
98107
99108/**
100109 * Returns the representation of a node as XML text.
110+ * In general it is not used by XSLT, that uses `xmlTransformedText` instead.
101111 * @param {XNode } node The starting node.
102112 * @param {XmlOutputOptions } options XML output options.
103113 * @returns The XML string.
114+ * @see xmlTransformedText
104115 */
105116export function xmlText ( node : XNode , options : XmlOutputOptions = {
106117 cData : false ,
107118 escape : true ,
108- selfClosingTags : true
119+ selfClosingTags : true ,
120+ outputMethod : 'xml'
109121} ) {
110122 const buffer : string [ ] = [ ] ;
111123 xmlTextRecursive ( node , buffer , options ) ;
@@ -133,7 +145,7 @@ function xmlTextRecursive(node: XNode, buffer: string[], options: XmlOutputOptio
133145 }
134146
135147 if ( node . childNodes . length === 0 ) {
136- if ( options . selfClosingTags ) {
148+ if ( options . selfClosingTags || ( options . outputMethod === 'html' && [ 'hr' , 'link' ] . includes ( node . nodeName ) ) ) {
137149 buffer . push ( '/>' ) ;
138150 } else {
139151 buffer . push ( `></${ xmlFullNodeName ( node ) } >` ) ;
@@ -163,7 +175,8 @@ export function xmlTransformedText(
163175 options : XmlOutputOptions = {
164176 cData : false ,
165177 escape : true ,
166- selfClosingTags : true
178+ selfClosingTags : true ,
179+ outputMethod : 'xml'
167180 }
168181) {
169182 const buffer : string [ ] = [ ] ;
@@ -175,14 +188,14 @@ function xmlTransformedTextRecursive(node: XNode, buffer: any[], options: XmlOut
175188 if ( node . visited ) return ;
176189 const nodeType = node . transformedNodeType || node . nodeType ;
177190 const nodeValue = node . transformedNodeValue || node . nodeValue ;
178- if ( nodeType == DOM_TEXT_NODE ) {
191+ if ( nodeType === DOM_TEXT_NODE ) {
179192 if ( node . transformedNodeValue && node . transformedNodeValue . trim ( ) !== '' ) {
180193 const finalText = node . escape && options . escape ?
181194 xmlEscapeText ( node . transformedNodeValue ) :
182195 node . transformedNodeValue ;
183196 buffer . push ( finalText ) ;
184197 }
185- } else if ( nodeType == DOM_CDATA_SECTION_NODE ) {
198+ } else if ( nodeType === DOM_CDATA_SECTION_NODE ) {
186199 if ( options . cData ) {
187200 buffer . push ( nodeValue ) ;
188201 } else {
@@ -199,7 +212,7 @@ function xmlTransformedTextRecursive(node: XNode, buffer: any[], options: XmlOut
199212 } else {
200213 xmlElementLogicMuted ( node , buffer , options ) ;
201214 }
202- } else if ( nodeType == DOM_DOCUMENT_NODE || nodeType == DOM_DOCUMENT_FRAGMENT_NODE ) {
215+ } else if ( nodeType === DOM_DOCUMENT_NODE || nodeType = == DOM_DOCUMENT_FRAGMENT_NODE ) {
203216 const childNodes = node . transformedChildNodes . concat ( node . childNodes ) ;
204217 childNodes . sort ( ( a , b ) => a . siblingPosition - b . siblingPosition ) ;
205218
@@ -235,7 +248,7 @@ function xmlElementLogicTrivial(node: XNode, buffer: string[], options: XmlOutpu
235248 let childNodes = node . transformedChildNodes . length > 0 ? node . transformedChildNodes : node . childNodes ;
236249 childNodes = childNodes . sort ( ( a , b ) => a . siblingPosition - b . siblingPosition ) ;
237250 if ( childNodes . length === 0 ) {
238- if ( options . selfClosingTags ) {
251+ if ( options . selfClosingTags || ( options . outputMethod === 'html' && [ 'hr' , 'link' ] . includes ( node . nodeName ) ) ) {
239252 buffer . push ( '/>' ) ;
240253 } else {
241254 buffer . push ( `></${ xmlFullNodeName ( node ) } >` ) ;
0 commit comments