Skip to content

xml ​

原文: https://finproducts.atlassian.net/wiki/spaces/JIDD3/pages/34793652649/FIN+5.3.1+xml 中文整理基于 FIN 5.3.1

导读: XML解析器和文档建模

以下为 API 参考,保留英文以便对照源码;目录已列出(英文标题便于检索);概述已尽量中译。


目录(导读) ​

  • classes
  • enums
  • errs
  • docs
  • Overview
  • DOM
  • Namespaces
  • Writing
  • Parsing
  • Slot Details
    • make
    • makeNs
    • name
    • ns
    • prefix
    • qname
    • toStr
    • uri
    • val
    • write
    • add
    • docType
    • nodeType
    • pis
    • removePi
    • root
    • publicId
    • rootElem
    • systemId
    • addAttr
    • attr
    • attrs
    • children
    • clearAttrs
    • copy
    • each
    • eachAttr
    • elem
    • elems
    • get
    • line
    • remove
    • removeAt
    • removeAttr
    • removeAttrAt
    • text
    • col
    • doc
    • parent
    • writeToStr
    • elemEnd
    • elemStart
    • fromStr
    • pi
    • vals
    • equals
    • hash
    • isDefault
    • close
    • depth
    • elemAt
    • next
    • parseDoc
    • parseElem
    • skip
    • target
    • cdata

API 正文(英文) ​

errs ​

XErrXML exception.
XIncompleteErrIncomplete document exception indicates that the end of stream was reached before the end of the document was parsed.

docs ​

Overview ​

The xml API provides the core APIs for working with XML:

  1. XElem: Provides a standard representation of an XML element tree to be used in memory. It is similar to the W3's DOM, but Fantom centric.
  2. XParser: is a non-validating XML parser. It may be used in two modes: to read an entire XML document into memory or as a pull-parser.

The features supported by XParser:

  • All element, attribute, processing instructions, and character data productions are supported
  • CDATA sections are supported
  • Namespaces are supported at both the element and attribute level
  • Doctype declarations provide access to the public and system identifiers
  • DTDs are ignored (as such you can't use internal or external entity declarations)
  • No access to comments is provided by the XML parser
  • Character data consisting only of whitespace is always ignored

DOM ​

XML documents are modeled in memory using the following classes:

  • XDoc: models the entire document providing access to the root element, doctype, and processing instructions declared before the root element
  • XElem: models an element name, attributes, and children nodes
  • XText: models character data in an element
  • XPi: models a processing instruction
  • XAttr: models an attribute name/value pair
  • XNs: models the prefix and URI of a XML namespace

XML documents are structured as a tree of nodes using the classes listed above. Typically the tree is built by parsing a XML document from an input stream. But you can construct a document in memory using the APIs and it-blocks:

doc := XDoc
{
  XElem("root")
  {
    XElem("a") { addAttr("flags", "0"); XText("blah"), },
    XElem("b") { XElem("c"), },
    XElem("m") { XText("I "), XElem("i") { XText("mean"), }, XText(" it!"), },
  },
}
doc.write(Env.cur.out)

// would print the following to the console
<?xml version='1.0' encoding='UTF-8'?>
<root>
 <a flags='0'>blah</a>
 <b>
  <c/>
 </b>
 <m>I <i>mean</i> it!</m>
</root>

Namespaces ​

The XNs class is used model XML namespaces. The default namespace is indicated with the prefix of "". Both XElem and XAttr define a set of methods for working with qualified names:

ns := XNs("x", `urn:foo`)
e := XElem("name", ns)

e.ns      =>  ns
e.prefix  =>  "x"
e.uri     =>  `urn:foo`
e.name    =>  "name"
e.qname   =>  "x:name"

If you construct a document by hand, then you are responsible for creating each element with the correct XNs and ensuring that the appropriate namespace attributes are declared:

nsDef := XNs("", `http://foo/default`)
nsBar := XNs("b", `http://foo/bar`)
root := XElem("root", nsBar)
{
  XAttr.makeNs(nsDef),
  XAttr.makeNs(nsBar),
  XElem("elem", nsDef),
  XElem("elem", nsBar),
}
root.write(Env.cur.out)

// would print the following to the console
<b:root xmlns='http://foo/default' xmlns:b='http://foo/bar'>
 <elem/>
 <b:elem/>
</b:root>

Writing ​

All the XML node classes support a write method which takes an OutStream. During debugging it is often convenient to write to standard out:

node.write(Env.cur.out)
Env.cur.out.flush

To write an XML document from memory to a file:

out := `test.xml`.toFile.out
doc.write(out)
out.close

If you are generating an XML document on the fly you might want to use OutStream directly. It supports escaping XML control characters via the writeXml method:

// escape markup in text
out.writeChars("<text>").writeXml(text).writeChars("</text>")

// escape markup and quotes
out.writeChars("attr='").writeXml(attrVal, OutStream.xmlEscQuotes).writeChars("'")

You can use Str.toXml to generate a string with XML markup escaped. However, you should prefer OutStream when streaming which is more efficient.

Parsing ​

The XParser class is used to parse XML input streams into XElems. The easiest way to do this is to parse the entire document into memory using the parseDoc method:

// parse and close input stream
doc := XParser(in).parseDoc

// parse a file
doc := XParser(`test.xml`.toFile.in).parseDoc

// parse a string
doc := XParser("<foo/>".in).parseDoc

The code above parses the document entirely into memory. This tends to be easiest way to work with XML documents. However it can create efficiency problems when parsing large documents, especially when mapping the XElems into other data structures. To support more efficient parsing of XML streams, XParser may also be used to read elements off the input stream one at a time. This is similar to the SAX API, except you pull events instead of having them pushed to you.

To perform pull parsing, use the next method to iterate through the document. This tokenizes the stream into XElem, XText, and XPi chunks. Each call to next advances to the next token and returns its node type. You may also check the type of the current token using nodeType. You may access the current token using elem, text, or pi.

XParser maintains a stack of XElems for you from the root element down to the current element. You may check the depth of the stack using the depth method. Get the current element at any position in the stack via elemAt.

It is very important to understand the XElem at given depth is only valid until the parser returns elemEnd for that depth. After that the element will be reused. A XText instance is only valid until the next call to next. You can make a safe copy of nodes using copy. You can also use parseElem to read the current element and its is descendants into memory during pull-parsing.

Example of pull parsing:

parser := XParser(
  "<root>
     <a>text</a>
   </root>".in)

while (parser.next != null)
  echo("$parser.nodeType $parser.depth $parser.elem")

// prints the following to the console
elemStart 0 <root>
elemStart 1 <a>
text      1 <a>
elemEnd   1 <a>
elemEnd   0 <root>

XAttr ​

@Js const class XAttr : Obj

XAttr models an XML attribute in an element. Attributes are immutable and may be shared across multiple XElem parents.

Constructors

makeConstruct an element with unqualified local name, value, and optional XML namespace.
makeNsConstruct an attribute which defines a namespace with "xmlns:<prefix>" name and uri value.

Fields

nameUnqualified local name of the attribute.
nsThe XML namespace which qualified this attribute's name.
valValue of the attribute.

Methods

prefixIf this attribute is qualified by an XML namespace then return the namespace's prefix.
qnameQualified name of the attribute.
toStrReturn this attribute name/value pair as string.
uriIf this element is qualified by an XML namespace then return the namespace's uri.
writeWrite this attribute to the output stream.

Slot Details ​


make ​

new make(Str name, Str val, XNs? ns := null)

Construct an element with unqualified local name, value, and optional XML namespace. The XNs instance should be defined as an attribute on an ancestor element. Throw ArgErr if an attempt is made to qualify the attribute by the default namespace with prefix of "".


makeNs ​

new makeNs(XNs ns)

Construct an attribute which defines a namespace with "xmlns:<prefix>" name and uri value. If prefix is "" then construct the default namespace attribute named "xmlns".


name ​

const Str name

Unqualified local name of the attribute. If an XML namespace prefix was specified, then this is everything after the colon:

foo='val'   =>  foo
x:foo='val' =>  foo

Note that attributes which start with "xml:" and "xmlns:" are not treated as a namespace:

xml:lang='en' => xml:lang
XML:lang='en' => xml:lang

ns ​

const XNs? ns

The XML namespace which qualified this attribute's name. If the attribute name is unqualified return null.


prefix ​

Str? prefix()

If this attribute is qualified by an XML namespace then return the namespace's prefix. Otherwise return null. Note an attribute can never be qualified by the default namespace.


qname ​

Str qname()

Qualified name of the attribute. This is the full name including the XML namespace prefix:

foo='val'   =>  foo
x:foo='val' =>  x:foo

toStr ​

virtual override Str toStr()

Return this attribute name/value pair as string.


uri ​

Uri? uri()

If this element is qualified by an XML namespace then return the namespace's uri. Otherwise return null.


val ​

const Str val

Value of the attribute.


write ​

Void write(OutStream out)

Write this attribute to the output stream.


XDoc ​

@Js class XDoc : XNode

XML document encapsulates the root element and document type.

Constructors

makeConstruct with optional root elem.

Fields

docTypeDocument type declaration or null if undefined.
rootRoot element.

Methods

addAdd a node to the document.
nodeTypeReturn the XNodeType.doc.
pisGet any processing instructions declared before the root element.
removePiRemove the processing instruction by reference.
toStrReturn string representation.
writeWrite this node to the output stream.

Slot Details ​


add ​

@Operator This add(Obj child)

Add a node to the document. If the node is an XElem then it is defined as the root element, otherwise the child must be a XPi. Return this.


docType ​

XDocType? docType

Document type declaration or null if undefined.


make ​

new make(XElem? root := null)

Construct with optional root elem.


nodeType ​

virtual override XNodeType nodeType()

Return the XNodeType.doc.


pis ​

XNode[] pis()

Get any processing instructions declared before the root element. Processing instructions after the root are not supported.


removePi ​

XPi? removePi(XPi pi)

Remove the processing instruction by reference.


root ​

XElem root

Root element.


toStr ​

virtual override Str toStr()

Return string representation.


write ​

virtual override Void write(OutStream out)

Write this node to the output stream.


XDocType ​

@Js class XDocType : Obj

XML document type declaration (but not the whole DTD).

Fields

publicIdPublic ID of an external DTD or null.
rootElemElement name of of the document.
systemIdSystem ID of an external DTD or null.

Methods

toStrReturn string representation of this processing instruction.

Slot Details ​


publicId ​

Str? publicId

Public ID of an external DTD or null.


rootElem ​

Str rootElem := "undefined"

Element name of of the document.


systemId ​

Uri? systemId

System ID of an external DTD or null.


toStr ​

virtual override Str toStr()

Return string representation of this processing instruction.


XElem ​

@Js class XElem : XNode

Models an XML element: its name, attributes, and children nodes.

Constructors

makeConstruct an element with unqualified local name and optional XML namespace.

Fields

lineLine number of XML element in source file or zero if unknown.
nameUnqualified local name of the element.
nsThe XML namespace which qualified this element's name.

Methods

addIf child is a XAttr then add an attribute.
addAttrAdd an attribute to this element.
attrGet an attribute by its non-qualified local name.
attrsGet this element's attributes as a readonly list.
childrenGet this element's children elements, text, and PIs as a readonly list.
clearAttrsRemove all the attributes.
copyMake a shallow copy of this element.
eachIterate each child element, text, and PI node in the children list.
eachAttrIterate each attribute in the attrs list.
elemFind an element by its non-qualified local name.
elemsGet the children elements.
getGet an attribute value by its non-qualified local name.
nodeTypeReturn the XNodeType.elem.
prefixIf this element is qualified by an XML namespace then return the namespace's prefix.
qnameQualified name of the element.
removeRemove the child element, text, or PI from this element.
removeAtRemove the child element, text, or PI at the specified index into children.
removeAttrRemove the attribute from this element.
removeAttrAtRemove the attribute at the specified index into attrs.
textReturn this element's child text node.
toStrString representation is as a start tag.
uriIf this element is qualified by an XML namespace then return the namespace's uri.
writeWrite this node to the output stream.

Slot Details ​


add ​

@Operator This add(Obj child)

If child is a XAttr then add an attribute. Otherwise it must be a XElem, XText, or XPi and is added a child node. If the child node is already parented, then throw ArgErr. Return this.


addAttr ​

This addAttr(Str name, Str val, XNs? ns := null)

Add an attribute to this element. Return this. This method is a convenience for:

add(XAttr(name, val, ns))

attr ​

XAttr? attr(Str name, Bool checked := true)

Get an attribute by its non-qualified local name. If the attribute is not found and checked is false then return null otherwise throw XErr.


attrs ​

XAttr[] attrs()

Get this element's attributes as a readonly list.


children ​

XNode[] children()

Get this element's children elements, text, and PIs as a readonly list.


clearAttrs ​

This clearAttrs()

Remove all the attributes. Return this.


copy ​

This copy()

Make a shallow copy of this element.


each ​

Void each(|XNode,Int| f)

Iterate each child element, text, and PI node in the children list.


eachAttr ​

Void eachAttr(|XAttr,Int| f)

Iterate each attribute in the attrs list.


elem ​

XElem? elem(Str name, Bool checked := true)

Find an element by its non-qualified local name. If there are multiple child elements with the name, then the first one is returned. If the element is not found and checked is false then return null otherwise throw XErr.


elems ​

XElem[] elems()

Get the children elements. If this element contains text or PI nodes, then they are excluded in the result.


get ​

@Operator Str? get(Str name, Bool checked := true)

Get an attribute value by its non-qualified local name. If the attribute is not found and checked is false then return null otherwise throw XErr.


line ​

Int line

Line number of XML element in source file or zero if unknown.


make ​

new make(Str name, XNs? ns := null)

Construct an element with unqualified local name and optional XML namespace. The XNs instance should be defined as an attribute on this or an ancestor element (see XAttr.makeNs).


name ​

Str name

Unqualified local name of the element. If an XML namespace prefix was specified, then this is everything after the colon:

<foo>    =>  foo
<x:foo>  =>  foo

nodeType ​

virtual override XNodeType nodeType()

Return the XNodeType.elem. Note that during pull parsing XParser will return elemStart and elemEnd.


ns ​

XNs? ns

The XML namespace which qualified this element's name. If the element name is unqualified return null.


prefix ​

Str? prefix()

If this element is qualified by an XML namespace then return the namespace's prefix. Otherwise return null. If the namespace is the default namespace then prefix is "".


qname ​

Str qname()

Qualified name of the element. This is the full name including the XML namespace prefix:

<foo>    =>  foo
<x:foo>  =>  x:foo

remove ​

XNode? remove(XNode child)

Remove the child element, text, or PI from this element. The child is matched by reference, so you must pass in the same XNode contained by this element. Return the removed node or null if no match.


removeAt ​

XNode removeAt(Int index)

Remove the child element, text, or PI at the specified index into children. Return the removed node.


removeAttr ​

XAttr? removeAttr(XAttr attr)

Remove the attribute from this element. The attribute is matched by reference, so you must pass in the same XAttr contained by this element. Return the removed attribute or null if no match.


removeAttrAt ​

XAttr removeAttrAt(Int index)

Remove the attribute at the specified index into attrs. Return the removed attribute.


text ​

XText? text()

Return this element's child text node. If this element contains multiple text nodes then return the first one. If this element does not contain a text node return null.


toStr ​

virtual override Str toStr()

String representation is as a start tag.


uri ​

Uri? uri()

If this element is qualified by an XML namespace then return the namespace's uri. Otherwise return null.


write ​

virtual override Void write(OutStream out)

Write this node to the output stream.


XErr ​

@Js const class XErr : Err

XML exception.

Constructors

makeConstruct with optional message, line number, and root cause.

Fields

colColumn number of XML error or zero if unknown.
lineLine number of XML error or zero if unknown.

Methods

toStrString representation.

Slot Details ​


col ​

const Int col

Column number of XML error or zero if unknown.


line ​

const Int line

Line number of XML error or zero if unknown.


make ​

new make(Str? message := null, Int line := 0, Int col := 0, Err? cause := null)

Construct with optional message, line number, and root cause.


toStr ​

virtual override Str toStr()

String representation.


XIncompleteErr ​

@Js const class XIncompleteErr : XErr

Incomplete document exception indicates that the end of stream was reached before the end of the document was parsed.

Constructors

makeConstruct with optional message, line number, and root cause.

Slot Details ​


make ​

new make(Str? message := null, Int line := 0, Int col := 0, Err? cause := null)

Construct with optional message, line number, and root cause.


XNode ​

@Js abstract class XNode : Obj

XNode is the base class for XElem and XText.

Fields

parentGet the parent of this node or null if unmounted.

Methods

docGet the root document node or null if this node is not mounted under a XDoc instance.
nodeTypeReturn the node type enum.
writeWrite this node to the output stream.
writeToStrConveniece to write to an in-memory string.

Slot Details ​


doc ​

XDoc? doc()

Get the root document node or null if this node is not mounted under a XDoc instance.


nodeType ​

abstract XNodeType nodeType()

Return the node type enum. Note that XElem always returns elem, but that during pull parsing XParser will return elemStart and elemEnd.


parent ​

XNode? parent { internal set }

Get the parent of this node or null if unmounted.


write ​

abstract Void write(OutStream out)

Write this node to the output stream.


writeToStr ​

Str writeToStr()

Conveniece to write to an in-memory string.


XNodeType ​

@Js @Serializable { simple=true } enum class XNodeType : Enum

Enumerates the type of XNode and current node of XParser.

Enum

docDocument node type by XDoc.nodeType
elemElement node type returned by XElem.nodeType
textText node type returned by XText.nodeType
piProcessing instruction node type returned by XPi.nodeType
elemStartStart of element used by XParser when pull parsing.
elemEndEnd of element used by XParser when pull parsing.

Constructors

fromStrReturn the XNodeType instance for the specified name.

Fields

valsList of XNodeType values indexed by ordinal

Slot Details ​


doc ​

const static XNodeType doc := ...

Document node type by XDoc.nodeType


elem ​

const static XNodeType elem := ...

Element node type returned by XElem.nodeType


elemEnd ​

const static XNodeType elemEnd := ...

End of element used by XParser when pull parsing.


elemStart ​

const static XNodeType elemStart := ...

Start of element used by XParser when pull parsing.


fromStr ​

static new fromStr(Str name, Bool checked := true)

Return the XNodeType instance for the specified name. If not a valid name and checked is false return null, otherwise throw ParseErr.


pi ​

const static XNodeType pi := ...

Processing instruction node type returned by XPi.nodeType


text ​

const static XNodeType text := ...

Text node type returned by XText.nodeType


vals ​

const static XNodeType[] vals := ...

List of XNodeType values indexed by ordinal


XNs ​

@Js const class XNs : Obj

Models a XML Namespace uri. It also defines a prefix to use to qualify element and attribute names. XNs instances are passed to the constructor of XElem and XAttr. You can define the namespace attribute via XAttr.makeNs.

Constructors

makeConstruct an XML namespace with the specified prefix and Uri.

Fields

prefixThe prefix used to quality element and attribute names with this namespace's uri.
uriThe uri which defines a universally unique namespace.

Methods

equalsTwo namespaces are equal if they have the same uri.
hashReturn the uri's hash code.
isDefaultReturn if this a default namespace which has a prefix of "".
toStrReturn the uri as the string representation.

Slot Details ​


equals ​

virtual override Bool equals(Obj? that)

Two namespaces are equal if they have the same uri.


hash ​

virtual override Int hash()

Return the uri's hash code.


isDefault ​

Bool isDefault()

Return if this a default namespace which has a prefix of "".


make ​

new make(Str prefix, Uri uri)

Construct an XML namespace with the specified prefix and Uri. Pass "" for prefix if this is the default XML namespace.


prefix ​

const Str prefix

The prefix used to quality element and attribute names with this namespace's uri. If this is the default namespace prefix is "".


toStr ​

virtual override Str toStr()

Return the uri as the string representation.


uri ​

const Uri uri

The uri which defines a universally unique namespace.


XParser ​

@Js class XParser : Obj

XParser is a simple, lightweight XML parser. It may be used as a pull parser by iterating through the element and text sections of an XML stream or it may be used to read an entire XML tree into memory as XElems.

Constructors

makeConstruct input stream to read.

Fields

colCurrent one based column number.
depthGet the depth of the current element with the document.
docGet the root document node.
lineCurrent one based line number.
nodeTypeGet the current node type constant which is always the result of the last call to next.

Methods

closeClose the underlying input stream.
elemGet the current element if nodeType is elemStart or elemEnd.
elemAtGet the element at the specified depth.
nextAdvance the parser to the next node and return the node type.
parseDocParse the entire document into memory as a tree of XElems and optionally close the underlying input stream.
parseElemParse the current element entirely into memory as a tree of XElems and optionally close the underlying input stream.
piif the current node type is pi return the XPi instance otherwise return null.
skipSkip parses all the content until reaching the end tag of the specified depth.
textIf the current type is text the XText instance used to store the character data.

Slot Details ​


close ​

Bool close()

Close the underlying input stream. Return true if the stream was closed successfully or false if the stream was closed abnormally.


col ​

Int col := 1 { private set }

Current one based column number.


depth ​

Int depth := -1 { private set }

Get the depth of the current element with the document. A depth of zero indicates the root element. A depth of -1 indicates a position before or after the root element.


doc ​

XDoc doc := XDoc.<ctor>() { private set }

Get the root document node.


elem ​

XElem? elem()

Get the current element if nodeType is elemStart or elemEnd. If nodeType is text or pi then this is the parent element. After elemEnd this XElem instance is no longer valid and will be reused for further processing. If depth is -1 return null.


elemAt ​

XElem elemAt(Int depth)

Get the element at the specified depth. Depth must be between 0 and depth inclusively. Calling elemAt(0) will return the root element and elemAt(depth) returns the current element. If depth is invalid IndexErr is thrown.


line ​

Int line := 1 { private set }

Current one based line number.


make ​

new make(InStream in)

Construct input stream to read.


next ​

XNodeType? next()

Advance the parser to the next node and return the node type. Return the current node type:

  • XNodeType.elemStart
  • XNodeType.elemEnd
  • XNodeType.text
  • XNodeType.pi
  • null indicates end of stream Also see nodeType.

nodeType ​

XNodeType? nodeType { private set }

Get the current node type constant which is always the result of the last call to next. Node type will be:

  • XNodeType.elemStart
  • XNodeType.elemEnd
  • XNodeType.text
  • XNodeType.pi
  • null indicates end of stream

parseDoc ​

XDoc parseDoc(Bool close := true)

Parse the entire document into memory as a tree of XElems and optionally close the underlying input stream.


parseElem ​

XElem parseElem(Bool close := true)

Parse the current element entirely into memory as a tree of XElems and optionally close the underlying input stream.


pi ​

XPi? pi()

if the current node type is pi return the XPi instance otherwise return null.


skip ​

Void skip(Int toDepth := this.depth)

Skip parses all the content until reaching the end tag of the specified depth. When this method returns, the next call to next will return the node immediately following the end tag.


text ​

XText? text()

If the current type is text the XText instance used to store the character data. After a call to next this XText instance is no longer valid and will be reused for further processing. If the current type is not text then return null.


XPi ​

@Js class XPi : XNode

XML processing instruction node.

Constructors

makeConstruct a processing instruction with specified target and val.

Fields

targetTarget name for the processing instruction.
valString value of processing instruction.

Methods

nodeTypeReturn the XNodeType.pi.
toStrReturn string representation of this processing instruction.
writeWrite this node to the output stream.

Slot Details ​


make ​

new make(Str target, Str val)

Construct a processing instruction with specified target and val.


nodeType ​

virtual override XNodeType nodeType()

Return the XNodeType.pi.


target ​

Str target

Target name for the processing instruction. It must be a valid XML name production.


toStr ​

virtual override Str toStr()

Return string representation of this processing instruction.


val ​

Str val

String value of processing instruction. This value must not contain the "?>".


write ​

virtual override Void write(OutStream out)

Write this node to the output stream.


XText ​

@Js class XText : XNode

XText represents the character data inside an element.

Constructors

makeConstruct a text node with the specified value.

Fields

cdataIf true then this text node was read/will be written as a CDATA section.
valCharacter data for this text node.

Methods

copyMake a copy of this text node.
nodeTypeReturn the XNodeType.text.
toStrReturn the string value (truncated if it is long).
writeWrite this node to the output stream.

Slot Details ​


cdata ​

Bool cdata

If true then this text node was read/will be written as a CDATA section. If set to true, then val must not contain the "]]>" substring.


copy ​

This copy()

Make a copy of this text node.


make ​

new make(Str val)

Construct a text node with the specified value.


nodeType ​

virtual override XNodeType nodeType()

Return the XNodeType.text.


toStr ​

virtual override Str toStr()

Return the string value (truncated if it is long).


val ​

Str val

Character data for this text node. If this text is to be written as a CDATA section, then this value must not contain the "]]>" substring.


write ​

virtual override Void write(OutStream out)

Write this node to the output stream. If this node is set to be written as a CDATA section and the val string contains the "]]>" substring then throw IOErr.