XML PROCESSING UTILITIES 2.0

Revision History

Date Revision Description Author
18 May 2000 Version 1.1 Initial documentation written for this product by Science Applications International Corporation (SAIC). Science Applications International Corporation of San Diego, CA
07 Feb 2002 Patch XT*7.3*58 Reviewed and edited documentation for VistA standards and format. Added new chapter named "XML Parser Use Example." Wally Fort, Susan Strack
Office of Information, Oakland, CA
25 Jul 2003 Patch XT*7.3*67 Two new XML Document Creation Utility APIs introduced with Patch XT*7.3*67. Wally Fort, Susan Strack, Thom Blom
Office of Information, Oakland, CA
05 Aug 2013 XML PROCESSING UTILITIES 2.0 Expanded section on XML creation tools; new sections XML Templating and XML Querying using XPATH. Converted manual into markdown format. Sam Habiel, Kathy Ice
VISTA Expertise Network, Seattle, WA

Introduction

VISTA XML Processing Utilities cover 4 different domains:

XML Parsing

The VistA Extensible Markup Language (XML) Parser is a full-featured, validating XML parser written in the M programming language and designed to interface with the VistA suite of M-based applications. It is not a standalone product. Rather, it acts as a server application that can provide XML parsing capabilities to any client application that subscribes to the application programmer interface (API) specification detailed in this document.

The VistA XML Parser employs two very different API implementations. The first is an event-driven interface that is modeled after the widely used Simple API for XML (SAX) interface specification. In this implementation, a client application provides a special handler for each parsing event of interest. When the client invokes the parser, it conveys not only the document to be parsed, but also the entry points for each of its event handlers. As the parser progresses through the document, it invokes the client’s handlers for each parsing event for which a handler has been registered.

The second API implementation is based on the World Wide Web Consortium (W3C’s) Document Object Model (DOM) specification. This API, which is actually built on top of the event-driven interface, first constructs an in-memory model of the fully parsed document. It then provides methods to navigate through and extract information from the parsed document.

The choice of which API to employ is in part dependent on the needs of the application developer. The event-driven interface requires the client application to process the document in a strictly top-down manner. In contrast, the in-memory model provides the ability to move freely throughout the document and has the added advantage of ensuring that the document is well formed and valid before any information is returned to the client application.

The VistA XML Parser employs an Entity Catalog to allow storage of external entities such as document type definitions. The Entity Catalog is a VA FileMan-compatible database and can be manipulated using the usual VA FileMan tools.

Term Definitions and XML Parser Concept

To understand the terms used in this documentation and the concept of the operation of an XML Parser, please review the W3C Architecture Domain website, Extensible Markup Language (XML) page at: http://www.w3.org/XML/.

Known Issues

The following are known issues in this version of the XML parser. Some of these are due to certain limitations of the M programming language.

Unlike languages like Java that have multiple character encoding support built-in, M does not recognize character encodings that do not incorporate the printable ASCII character subset. Thus, 16-bit character encodings such as Unicode are not supported. Fortunately, a large number of 8-bit character encodings do incorporate the printable ASCII character subset and can be parsed. Because of this limitation, the VistA XML Parser will reject any documents with unsupported character encodings.

The current version of the VistA XML Parser does not support retrieval of external entities using the HTTP or FTP protocols (or for that matter, any protocols other than the standard file access protocols of the underlying operating system). Client applications using the event-driven interface can intercept external entity retrieval by the parser and implement support for these protocols if desired.

The parser uses the Kernel function FTG^%ZISH for file access. This function reads the entire contents of a file into an M global. There are several nuances to this function that manifest themselves in parser operation:

Files are opened with a time-out parameter. If an attempt is made to access a non-existent file, there is a delay of a few seconds before the error is signaled.

FTG^%ZISH doesn’t work on GT.M because of the %ZISH call is non-supported. Instead, the programmer must load the file into a global first and send that global into the parser.

Files are accessed in text mode. The result is that certain imbedded control characters are stripped from the input stream and never detected by the parser. Because these control characters are disallowed by XML, the parser will not report such documents as non-conforming.

A line feed / carriage return sequence at the end of a document is stripped and not presented to the parser. Only in rare circumstances would this be considered significant data, but in the strictest sense should be preserved.

The parser allows external entities to contain substitution text that in some cases would violate XML rules that state that a document must be conforming in the absence of resolving such references. In other words, XML states that a non-validating parser should be able to verify that a document is conforming without processing external entities. This restriction constrains how token streams can be continued across entities. The parser recognizes most, but not all, of these restrictions. The effect is that the parser is more lax in allowing certain kinds of entity substitutions.

Parsers vary in how they enforce whitespace that is designated as required by the XML specification. This parser will flag the absence of any required whitespace as a conformance error, even in situations where the absence of such whitespace would not introduce syntactic ambiguity. The result is that this parser will reject some documents that may be accepted by other parsers.

Event-Driven API

The event-driven Application Programmer Interface (API) is based on the well-established Simple API for XML (SAX) interface employed by many XML parsers. This API, Table 1, has a single method. (Figure 1 spans two pages.)

EN^MXMLPRSE(DOC,CBK,OPT)

Table 1: EN^MXMLPRSE—Event-Driven API based on SAX interface
Parameter Type Required? Description
DOC String Yes This is either a closed reference to a global root containing the document or a filename and path reference identifying the document on the host system. If a global root is passed, the document must either be stored in standard FileMan word- processing format or may occur in sequentially numbered nodes below the root node. Thus, if the global reference is “^XYZ”, the global must be of one of the following formats:
^XYZ(1,0) = "LINE 1"
^XYZ(2,0) = "LINE 2" ...
or
^XYZ(1) = "LINE 1"
^XYZ(2) = "LINE 2" ...
CBK Local array (by reference) No This is a local array, passed by reference that contains a list of parse events and the entry points for the handlers of those events. The format for each entry is:
CBK(<event type>) = <entry point>

The entry point must reference a valid entry point in an existing M routine and should be of the format tag^routine. The entry should not contain any formal parameter references. The application developer is responsible for ensuring that the actual entry point contains the appropriate number of formal parameters for the event type. For example, client application might register its STARTELEMENT event handler as follows:
CBK(“STARTELEMENT”) = “STELE^CLNT”
The actual entry point in the CLNT routine must include two formal parameters as in the example:
STELE(ELE,ATR) <handler code>
For the types of supported events and their required parameters, see the discussion on the pages that follows.
OPT String No This is a list of option flags that control parser behavior. Recognized option flags are:
  • W = Do not report warnings to the client.
  • V = Validate the document. If not specified, the parser only checks for conformance.
  • 0 = Terminate parsing on encountering a warning.
  • 1 = Terminate parsing on encountering a validation error. (By default, the parser terminates only when a conformance error is encountered.)

Event Types Recognized by Vista XML Parser

Table 2: Event types recognized by the VISTA XML Parser
Event Type Parameter(s) Description
STARTDOCUMENT None Notifies the client that document parsing has commenced.
ENDDOCUMENT None Notifies the client that document parsing has completed.
DOCTYPE ROOT
PUBID
SYSID
Notifies the client that a DOCTYPE declaration has been encountered. The name of the document root is given by ROOT. The public and system identifiers of the external document type definition are given by PUBID and SYSID, respectively.
STARTELEMENT NAME
ATTRLIST
An element (tag) has been encountered. The name of the element is given in NAME. The list of attributes and their values is provided in the local array ATTRLST in the format: ATTRLST(<name>) = <value>
ENDELEMENT NAME A closing element (tag) has been encountered. The name of the element is given in NAME.
CHARACTERS NAME Non-markup content has been encountered. TEXT contains the text. Line breaks within the original document are represented as carriage return/line feed character sequences. The parser does not necessarily pass an entire line of the original document to the client with each event of this type.
PI TARGET
TEXT
The parser has encountered a processing instruction. TARGET is the target application for the processing instruction. TEXT is a local array containing the parameters for the instruction.
EXTERNAL SYSID
PUBID
GLOBAL
The parser has encountered an external entity reference whose system and public identifiers are given by SYSID and PUBID, respectively. If the event handler elects to retrieve the entity rather than allowing the parser to do so, it should pass the global root of the retrieved entity in the GLOBAL parameter. If the event handler wishes to suppress retrieval of the entity altogether, it should set both SYSID and PUBID to null.
NOTATION NAME
SYSID
PUBIC
The parser has encountered a notation declaration. The notation name is given by NAME. The system and public identifiers associated with the notation are given by SYSID and PUBIC, respectively.
COMMENT TEXT The parser has encountered a comment. TEXT is the text of the comment.
ERROR ERR The parser has encountered an error during the processing of a document. ERR is a local array containing information about the error. The format is:
  • ERR("SEV") = Severity of the error where 0 is a warning, 1 is a validation error, and 2 is a conformance error.
  • ERR("MSG") = Brief text description of the error.
  • ERR("ARG") = The token value the triggered the error (optional).
  • ERR("LIN") = The number of the line being processed when the error occurred.
  • ERR("POS") = The character position within the line where the error occurred.
  • ERR("XML") = The original document text of the line where the error occurred.

A sample client of the event-driven API is provided in the routine MXMLTEST. This routine has an entry point EN(DOC,OPT), where DOC and OPT are the same parameters as described above in Table 2 for the parser entry point. This sample application simply prints a summary of the parsing events as they occur.

In-Memory Document API

This Application Programmer Interface (API) is based on the W3C’s Document Object Model (DOM) specification. It first builds an “in-memory” image of the fully parsed and validated document and then provides a set of methods to permit structured traversal of the document and extraction of its contents. This API is actually layered on top of the event-driven API. In other words, it is actually a client of the event-driven API that in turn acts as a server to another client application.

The document image is represented internally as a tree with each node in the tree representing an element instance. Attributes (names and values), non-markup text, and comment text may be associated with any given node. For example, in Table 3 the XML document on the left is represented by the tree structure on the right.

Table 3: XML document (left) – Tree structure diagram (right)
	<top attr1="val1" attr2="val2">
	<child1>child1 text</child1>
	<child2>child2 text></child2>
	</top>
	
top (attr1 = val1; attr2 = val2)
  • Child1 (Child1 text)
  • Child2 (Child2 text)

The supported methods are documented on the pages that follow.

$$EN^MXMLDOM(DOC,OPT)

This is the entry point to perform initial processing of the XML document. The client application must first call this entry point to build the in-memory image of the document before the remaining methods can be applied. The return value is a handle to the document instance that was created and is used by the remaining API calls to identify a specific document instance. The parameters for this entry point are listed in Table 4 by type, requirement (yes or no), and description.

Table 4: $$EN^MXMLDOM - Perform inital processing of XML document
Parameter Type Required Description
DOC String Yes Either a closed reference to a global root containing the document or a filename and path reference identifying the document on the host system. If a global root is passed, the document must either be stored in standard FileMan word-processing format or may occur in sequentially numbered nodes below the root node. Thus, if the global reference is "^XYZ", the global must be of one of the following formats:
	^XYZ(1,0) = "LINE 1"
	^XYZ(2,0) = "LINE 2" ...
	
or
	^XYZ(1) = "LINE 1"
	^XYZ(2) = "LINE 2" ...
	
OPT String No
  • W = Do not report warnings to the client.
  • V = Do not validate the document. If specified, the parser only checks for conformance.
  • 0 = Terminate parsing on encountering a warning.
  • 1 = Terminate parsing on encountering a validation error. (By default, the parser terminates only when a conformance error is encountered.)
Return value Integer   Returns a nonzero handle to the document instance if parsing completed successfully, or zero otherwise. This handle is passed to all other API methods to indicate which document instance is being referenced. This allows for multiple document instances to be processed concurrently.

DELETE^MXMLDOM(HANDLE)

This entry point deletes the specified document instance. A client application should always call this entry point when finished with a document instance. The parameter for this API is listed in Table 5 by type, requirement (yes or no), and description.

Table 5: DELETE^MXMLDOM—Delete specified document instance
Parameter Type Required Description
HANDLE Integer Yes The value returned by the $$EN^MXMLDOM call that created the in-memory document image.

$$NAME^MXMLDOM(HANDLE,NODE)

This entry point returns the name of the element at the specified node within the document parse tree. The parameters for this API are listed in Table 6 by type, requirement (yes or no), and description.

Table 6: $$NAME^MXMLDOM—Return element name at specified node in document parse tree
Parameter Type Required Description
HANDLE Integer Yes The value returned by the $$EN^MXMLDOM call that created the in-memory document image.
NODE Integer Yes The node whose associated element name is being retrieved.
Return value String The name of the element associated with the specified node.

$$CHILD^MXMLDOM(HANDLE,PARENT,CHILD)

Returns the node of the first or next child of a given parent node, or 0 if there are none remaining. The parameters for this API are listed in Table 7 by type, requirement (yes or no), and description.

Table 7: $$CHILD^MXMLDOM—Return parent node’s first or next child. 0 if none remaining.
Parameter Type Required Description
HANDLE Integer Yes The value returned by the $$EN^MXMLDOM call that created the in-memory document image.
PARENT Integer Yes The node whose children are being retrieved.
CHILD Integer No If specified, this is the last child node retrieved. The function will return the next child in the list. If the parameter is zero or missing, the first child is returned.
Return Value Integer   The next child node or zero if there are none remaining.

$$SIBLING^MXMLDOM(HANDLE,NODE)

Returns the node of the specified node’s immediate sibling, or 0 if there is none. The parameters for this API are listed in Table 8 by type, requirement (yes or no), and description.

Table 8: $$SIBLING^MXMLDOM—Return specified node’s immediate sibling. 0 if none remaining
Parameter Type Required Description
HANDLE Integer Yes The value returned by the $$EN^MXMLDOM call that created the in-memory document image.
NODE Integer Yes The node in the document tree whose sibling is being retrieved.
Return value Integer   The node corresponding to the immediate sibling of the specified node, or zero if there is none.

$$PARENT^MXMLDOM(HANDLE,NODE)

Returns the parent node of the specified node, or 0 if there is none. The parameters for this API are listed in Table 9 by type, requirement (yes or no), and description.

Table 9: $$PARENT^MXMLDOM—Return specified node’s parent node. 0 if none remaining
Parameter Type Required Description
HANDLE Integer Yes The value returned by the $$EN^MXMLDOM call that created the in-memory document image.
NODE Integer Yes The node in the document tree whose parent is being retrieved.
Return value String   The parent node of the specified node, or zero if there is no parent.

TEXT^MXMLDOM(HANDLE,NODE,TEXT) or $$TEXT^MXMLDOM(HANDLE,NODE,TEXT)

Extracts non-markup text associated with the specified node. The parameters for this API are listed in Table 10 by type, requirement (yes or no), and description.

Table 10: TEXT^MXMLDOM or $$TEXT^MXMLDOM—Extract specified node’s non-markup text
Parameter Type Required Description
HANDLE Integer Yes The value returned by the $$EN^MXMLDOM call that created the in-memory document image.
NODE Integer Yes The node in the document tree that is being referenced by this call.
TEXT String Yes This parameter must contain a closed local or global array reference that is to receive the text. The specified array is deleted before being populated.
Return value Boolean   If called as an extrinsic function, the return value is true if text was retrieved, or false if not.

CMNT^MXMLDOM(HANDLE,NODE,TEXT) or $$CMNT^MXMLDOM(HANDLE,NODE,TEXT)

Extracts comment text associated with the specified node. The parameters for this API are listed in Table 11 by type, requirement (yes or no), and description.

Table 11: CMNT^MXMLDOM or $$CMNT^MXMLDOM—Extract specified node’s comment text
Parameter Type Required Description
HANDLE Integer Yes The value returned by the $$EN^MXMLDOM call that created the in-memory document image.
NODE Integer Yes The node in the document tree that is being referenced by this call.
TEXT String Yes This parameter must contain a closed local or global array reference that is to receive the text. The specified array is deleted before being populated.
Return value Boolean   If called as an extrinsic function, the return value is true if text was retrieved, or false if not.

$$ATTRIB^MXMLDOM(HANDLE,NODE,ATTRIB)

Retrieves the first or next attribute associated with the specified node. The parameters for this API are listed in Table 12 by type, requirement (yes or no), and description.

Table 12: $$ATTRIB^MXMLDOM—Retrieve specified node’s first or next attribute
Parameter Type Required Description
HANDLE Integer Yes The value returned by the $$EN^MXMLDOM call that created the in-memory document image.
NODE Integer Yes The node whose attribute name is being retrieved.
ATTRIB String No The name of the last attribute retrieved by this call. If null or missing, the first attribute associated with the specified node is returned. Otherwise, the next attribute in the list is returned.
Return value String   The name of the first or next attribute associated with the specified node, or null if there are none remaining.

$$VALUE^MXMLDOM(HANDLE,NODE,ATTRIB)

Retrieves the value associated with the named attribute. The parameters for this API are listed in Table 13 by type, requirement (yes or no), and description.

Table 13: $$VALUE^MXMLDOM—Retrieve value associated with named attribute
Parameter Type Required Description
HANDLE Integer Yes The value returned by the $$EN^MXMLDOM call that created the in-memory document image.
NODE Integer Yes The node whose attribute value is being retrieved.
ATTRIB String No The name of the attribute whose value is being retrieved by this call.
Return value String   The value associated with the specified attribute.

VistA XML Parser Usage Example

This is a simple example of how to use the VistA XML Parser with an XML document (file). The XML file contains a parent node named BOOKS. Nested within that parent node are child nodes named TITLE and AUTHOR.

Remember the following:

The parent node is the node whose child nodes are being retrieved.

The child node, if specified, is the last child node retrieved. The function will return the next child in the list. If the parameter is zero or missing, the first child is returned.

Create an XML File

Figure 1: VistA XML Parser Use Example—Create XML File

^TMP($J,1)=<?xml version='1.0'?>
^TMP($J,2)=<!DOCTYPE BOOK>
^TMP($J,3)=<BOOK>
^TMP($J,4)=<TITLE>Design Patterns</TITLE>
^TMP($J,5)=<AUTHOR>Gamma</AUTHOR>
^TMP($J,6)=<AUTHOR>Helm</AUTHOR>
^TMP($J,7)=<AUTHOR>Johnson</AUTHOR>
^TMP($J,8)=<AUTHOR>Vlissides</AUTHOR>
^TMP($J,9)=</BOOK>

Invoke Simple API for XML (SAX) Interface

Figure 2: VistA XML Parser Use Example—Invoke SAX Interface

D EN^MXMLTEST($NA(^TMP($J)),"V")<Enter>

… Now see what happens.

Check Document Object Model (DOM) Interface

Figure 3: VistA XML Parser Use Example—Check DOM Interface

>S HDL=$$EN^MXMLDOM($NA(^TMP($J))) <Enter>

 ; Write name of the first node
>W $$NAME^MXMLDOM(HDL,1) <Enter>
BOOK
 
 ; Get the child of the node
>S CHD=$$CHILD^MXMLDOM(HDL,1) <Enter>
 
 ; Write child name
>W $$NAME^MXMLDOM(HDL,CHD) <Enter>
TITLE
 ;
 ; Get the text of the child.
>W $$TEXT^MXMLDOM(HDL,CHD,$NA(VV)) <Enter>
1
 ;
>ZWRITE VV <Enter>
VV(1)=Design Patterns

List All Sibling Nodes

Figure 4: VistA XML Parser Use Example—List Sibling Nodes

>S CHD=$$CHILD^MXMLDOM(HDL,1) <Enter>
>S SIB=CHD <Enter>
>F S SIB=$$SIBLING^MXMLDOM(HDL,SIB) Q:SIB'>0 W !,SIB,?4,$$NAME^MXMLDOM(HDL,SIB) <Enter>
3 AUTHOR
4 AUTHOR
5 AUTHOR
6 AUTHOR
>

XML Querying using XPATH

XPATH^MXMLPATH allows you to query an already parsed MXML DOM using an XPATH expression. Most commonly used XPATH expressions are supported. The parser is stateful; so navigating to one node means that your current location is that node. When you resume searching, you start from that node (except if use / or // which automatically start from the top).

See http://www.w3.org/TR/xpath/ for the XPATH standard.

Only abbreviated syntax is supported. The following are supported and can be combined:

 * element name
 * @attribute name
 * /root/element2
 * /root/element1[n]/element2[n]
 * //element1/element2
 * element[n]
 * element[last()]
 * element[@attribute="value"]
 * element[@attribute]
 * element[childnode="value"]

The following syntax is not supported:

API

[$$]XPATH^MXMLPATH(RETURN,DOCHAND,XPATH)

XPATH query a parsed XML document represented by document handle DOCHAND and return the result in RETURN. If called as an extrsinsic function, the first node is returned. If attributes are requested, their values are returned as the values in the RETURN array. If the extrinsic function is called on attributes, the first attribute value is returned as the value of the extrinsic.

Table 12: [$$]XPATH^MXMLPATH—XPATH handler
Parameter Type Required Description
RETURN Pass by Reference. Contents killed first. No This is where data found in the query is returned. If no attribute is requested, the matched nodes will be returned as subscripts of RETURN, like the following
	RETURN(30)=""
	RETURN(31)=""
	RETURN(32)=""
	RETURN(33)=""
	RETURN(34)=""
    
If an attribute is requested in the XPATH expression, its value will be included in the return array like this: RETURN(nodenumber,attname)=attvalue An example:
	RETURN(2,"vuid")=400001
	RETURN(3,"vuid")=400002
	
DOCHAND Integer Yes The XML DOM Handle returned by $$EN^MXMLDOM
XPATH String Yes The XPATH expression
Return Value node number or string Will be returned if called as an extrinsic function If no attribute is requested, the first matched node is returned. If an attribute is requested, the attribute value of the first matched node is returned.

Examples

Example 1:

NEW XPATH SET XPATH="/PEPSResponse/Body/drugCheck/drugDrugChecks/drugDrugCheck/professionalMonograph/references/reference"
NEW RTN
DO XPATH^MXMLPATH(.RTN,DOCHAND,XPATH)
ZWRITE RTN

RTN(30)=""
RTN(31)=""
RTN(32)=""
RTN(33)=""
RTN(34)=""

N % S %=$$XPATH^MXMLPATH(,DOCHAND,XPATH)
W %,!

30

Example 2:

D XPATH^MXMLPATH(.RTN,DOCHAND,"//drug/@vuid")
ZWRITE RTN

RTN(15,"vuid")=778899

N % S %=$$XPATH^MXMLPATH(,DOCHAND,XPATH)
W %,!
778899

XML Document Creation Utility APIs

These Application Programmer Interfaces (API) have been developed to assist you in creating an XML document.

Simple/Singlet XML Building APIs

$$XMLHDR^MXMLUTL()

This extrinsic function returns a standard extensible markup language (XML) header for encoding XML messages. This API is a Supported Reference. Format:

$$XMLHDR^MXMLUTL()

Table 14: $$XMLHDR^MXMLUTL(STR)—Return a standard XML Message Headers
Parameter Type Required Description
Return value String   Standard XML header.

Example:

>S X=$$XMLHDR^MXMLUTL
>W X
<?xml version="1.0" encoding="utf-8" ?>

$$SYMENC^MXMLUTL(STR)

This extrinsic function replaces reserved XML symbols in a string with their XML encoding for strings used in an extensible markup language (XML) message. This API is a Supported Reference. Format:

$$SYMENC^MXMLUTL(STR)

Table 15: $$SYMENC^MXMLUTL(STR)—Encoded Strings in XML Messages
Parameter Type Required Description
STR String Yes String to be encoded in an XML message
Return value String   The input string with XML encoding replacing reserved XML symbols.

Example:

>S X=$$SYMENC^MXMLUTL("This line isn't &""<XML>"" safe as is.")

$$MKTAG^MXMLBLD(NAME,ATTRS,TEXT,CLOSE)

This extrinsic function creates an XML tag.

Table 16: $$MKTAG^MXMLBLD(NAME,ATTRS,TEXT,CLOSE)—Create an XML tag
Parameter Type Required Description
NAME String Yes Name of the xml element to write; or /Name to create a closing tag
ATTRS Array No Name Value pair of attributes. If not passed, no attributes are produced.
TEXT String No Text to include in the node. If not passed, No text is produced.
CLOSE Boolean (0 or 1) No Weather to close the XML tag. If not passed, the default behavior is to close the tag.

Examples:

>N %1
>S %1("type")="japaense"
>S %1("origin")="japan"
>W $$MKTAG^MXMLBLD("name",.%1,"Toyoda",1)         ; <name origin="japan" type="japaense">Toyoda</name>
>W $$MKTAG^MXMLBLD("name",.%1,"Toyoda")           ; <name origin="japan" type="japaense">Toyoda</name>
>W $$MKTAG^MXMLBLD("name",,"Toyoda")              ; <name>Toyoda</name>
>W $$MKTAG^MXMLBLD("name",.%1)                    ; <name origin="japan" type="japaense" />
>W $$MKTAG^MXMLBLD("name",.%1,,0)                 ; <name origin="japan" type="japaense">
>W $$MKTAG^MXMLBLD("/name");                      ; </name>

[$$]PUT^MXMLBLD(RETURN,STRING)

PUT is a convenience procedure/extrinsic function that adds a line to an array passed by reference.

Table 17: [$$]PUT^MXMLBLD - Add a line to an array
Parameter Type Required Description
RETURN Array passed by Reference Yes PUT adds an extra numeric subscript to the end of the array. The value of the subscripted entry is the string
STRING String Yes The string that will be the value to add to an array
Return value Integer   If called with $$, PUT will return the number of new subscript

Example:

>N RTN                                                                       
>D PUT^MXMLBLD(.RTN,$$XMLHDR^MXMLUTL())
>D PUT^MXMLBLD(.RTN,$$MKTAG^MXMLBLD("Book",,"Pride and Prejudice"))
>ZWRITE RTN
>RTN(1)="<?xml version=""1.0"" encoding=""utf-8"" ?>"
>RTN(2)="<Book>Pride and Prejudice</Book>"

Build APIs

This section includes the following calls which together provide a more complex API but complete API to build an XML document.

START^MXMLBLD(DOC,DOCTYPE,FLAG,NO1ST,ATT)

This procedure creates the first element in the doucment and also by default writes out the XML header and DOCTYPE.

Table 18: START^MXMLBLD - Start an XML document
Parameter Type Required Description
DOC String Yes Root element name
DOCTYPE String No DOCTYPE reference for the XML document
FLAG String No Only supported flag is "G". If not passed, the document builder will print the document as you write it to the current device. If passed, it will put the document under ^TMP("MXMLBLD",$J). By default, it's printed to the current device.
NO1ST Boolean (0 or 1) No If 1 is passed, the <?xml... XML header will not be included. By default, it's included.
ATT Array No Name value hash in the format ATT("name")="value". If not passed, no attributes are added.

END^MXMLBLD

This procedure closes the Start Root XML element. It doesn’t accept any parameters.

ITEM^MXMLBLD(INDENT,TAG,ATT,VALUE)

This procedure adds an xml element with no child elements, like <Book> History of Arabia<Book>.

Table 19: ITEM^MXMLBLD - Add an element without children
Parameter Type Required Description
INDENT Integer No Number of spaces to indent the item. Can be omitted for no indents.
TAG Tag name Yes Element Name
ATT Array No Name value hash in the format ATT("name")="value". If not passed, no attributes are added.
VALUE String No Text to put in the node.

MULTI^MXMLBLD(INDENT,TAG,ATT,DOITEM)

This procedure is used to add an element with child elements.

Table 20: MULTI^MXMLBLD - Add an element with children
Parameter Type Required Description
INDENT Integer No Number of spaces to indent the item. Can be omitted for no indents.
TAG Tag name Yes Element Name
ATT Array No Name value hash in the format ATT("name")="value". If not passed, no attributes are added.
ITEM Routine Tag Yes A entry point that calls ITEM or call MULTI^MXMLBLD recursively.

Example

TESTBLD1	; Test Wally's XML Builder
	N %1 S %1("version")="2.5"
	D START^MXMLBLD("Books",,"G",,.%1)
	N %1 S %1("type")="date"
	D ITEM^MXMLBLD(,"LastUpdated",.%1,"3-15-99")
	D MULTI^MXMLBLD(,"Book",,"BOOKEAC1")
	D MULTI^MXMLBLD(,"Book",,"BOOKEAC2")
	D END^MXMLBLD
	ZWRITE ^TMP("MXMLBLD",$J,*)
	QUIT
BOOKEAC1	; Book 1
	D ITEM^MXMLBLD(,"Author",,"AUSTEN,JANE")
	D ITEM^MXMLBLD(,"Title",,"PRIDE AND PREJUDICE")
	D ITEM^MXMLBLD(,"Description",,"A romantic novel revealing how pride can cloud our better judgement.")
	Q
BOOKEAC2	; Book 2
	D ITEM^MXMLBLD(,"Author",,"Johann Wolfgang von Goethe")
	D ITEM^MXMLBLD(,"Title",,"Sorrows of Young Werther")
	D ITEM^MXMLBLD(,"Description",,"A tale of unrequited love leading to the demise of the protagonist.")
	Q

Expected Output:

^TMP("MXMLBLD",5609,1)="<?xml version=""1.0"" encoding=""utf-8"" ?>"
^TMP("MXMLBLD",5609,2)="<Books version=""2.5"">"
^TMP("MXMLBLD",5609,3)="<LastUpdated type=""date"">3-15-99</LastUpdated>"
^TMP("MXMLBLD",5609,4)="<Book>"
^TMP("MXMLBLD",5609,5)="<Author>AUSTEN,JANE</Author>"
^TMP("MXMLBLD",5609,6)="<Title>PRIDE AND PREJUDICE</Title>"
^TMP("MXMLBLD",5609,7)="<Description>A romantic novel revealing how pride can cloud our better judgement.</Description>"
^TMP("MXMLBLD",5609,8)="</Book>"
^TMP("MXMLBLD",5609,9)="<Book>"
^TMP("MXMLBLD",5609,10)="<Author>Johann Wolfgang von Goethe</Author>"
^TMP("MXMLBLD",5609,11)="<Title>Sorrows of Young Werther</Title>"
^TMP("MXMLBLD",5609,12)="<Description>A tale of unrequited love leading to the demise of the protagonist.</Description>"
^TMP("MXMLBLD",5609,13)="</Book>"
^TMP("MXMLBLD",5609,14)="</Books>"

XML Templating functions

The routine MXMLTMPL and associated routines are reponsible for providing XML templating functions. You can do the following things with it:

The use case which this routine is best used for is creating XML documents that have repeating sections that come from VISTA data. For example, a medication XML template can be created by hand and then stored in Fileman. At runtime, each medication’s data can be extracted and then the placeholders substituted with the actual data; then this XML blob can be inserted into a larger XML document.

Warning: Because all array names are passed by name, name collision is a strong possibility. Make sure that all array names you pass in are namespaced if you are using local variables!

Array Creation

Array Manipulation

Mapping Placeholders

Printing for debugging purposes - PARY^MXMLTMPL(GLO,ZN)

Advanced functionality

In explanations of how this works, the following XML will be used as reference:

1 <?xml version="1.0" encoding="utf-8" ?>
2 <Books>
3 <LastUpdated date="@@LASTUP@@" />
4 <Book>
5 <Author>@@AUTHOR@@</Author>
6 <Title>@@TITLE@@</Title>
7 <Description>@@DES@@</Description>
8 </Book>
9 </Books>

Array Creation APIs

PUSH^MXMLTMP1(STK,VAL)

Pushes a value VAL to a named array STK (for stack). See examples at the end of this section.

Table 21: PUSH^MXMLTMP1 - Push a value into an array
Parameter Type Required Description
STK Mumps Name Yes The array name in which the value will be stored.
VAL String Yes Value to store (string)

POP^MXMLTMP1(STK,VAL)

Pops the last pushed item (at the bottom of STK) into VAL.

Table 22: POP^MXMLTMP1 - Pop a value from STK to VAL
Parameter Type Required Description
STK Mumps Name Yes The array name in which the value will be retrieved.
VAL Reference Yes Variable in which the value will be restored.

Example of Pop:

PUSHPOP2 ; Push and Pop
	N KBAN
	D PUSH^MXMLTMP1($NA(KBAN),"Test1")
	D PUSH^MXMLTMP1($NA(KBAN),"Test2")
	N KBANVAL
	D POP^MXMLTMP1($NA(KBAN),.KBANVAL)
	W KBANVAL,! ; Test2
	QUIT

QUERY^MXMLTMPL(IARY,XPATH,OARY)

This will get you XML associated with an pseudo-XPATH expression from IARY (Name) into OARY (Name). For example, from the reference XML cited at the beginning of this section, a pseudo-XPATH of “//Books/Book” returns the following:

<Book>
<Author>@@AUTHOR@@</Author>
<Title>@@TITLE@@</Title>
<Description>@@DES@@</Description>
</Book>

Warning: This is psuedo-XPATH syntax. It’s not real XPATH. See below for supported syntax

Table 24: QUERY^MXMLTMP1 - Pop a value from STK to VAL
Parameter Type Required Description
IARY Mumps Name Yes Input XML array by Name
XPATH String Yes Pseudo-XPATH. Only //head-node/child1/child2 is supported.
OARY Mumps Name Yes Output XML array by Name

CP^MXMLTMPL(CPSRC,CPDEST)

This copies an array from CPSRC (Name) to CPDEST (Name). A programmer may use the merge command instead as it provides the same functionality.

Table 25: CP^MXMLTMPL - Copy Arrays
Parameter Type Required Description
CPSRC Mumps Name Yes Source Array Name
CPDEST Mumps Name Yes Destination Array Name

Array Manipulation APIs

REPLACE^MXMLTMPL(REXML,RENEW,REXPATH)

Replaces the XML pointed to by REXPATH in REXML (name) by RENEW. The last tag in the REXPATH (e.g. c in //a/b/c) is where the replacement begins. For example, in the example below, a REXPATH of //Books/Book will replace lines 3 to 5.

1 <?xml ...>
2 <Books>
3 <Book>
4 <Author>Lord Byron</Author>
5 </Book>
6 </Books>

If RENEW is empty (””), The INNER XML pointed to XPATH gets deleted. So in the example above, only line 4 will be deleted.

Examples below in the DEMO program.

Table 26: REPLACE^MXMLTMPL - Replace XML in documents
Parameter Type Required Description
REXML Mumps Name Yes Original XML array whose contents will be replaced
RENEW Mumps Name Yes New contents array to be used for the replacement
REXPATH String Yes Psuedo-XPATH point at which to do the replacement. See QUERY above for format.

INSERT^MXMLTMPL(INSXML,INSNEW,INSXPATH)

Inserts XML in INSNEW in XML of INSXML at the Pseudo-XPATH point. If there are existing children at the INSXPATH point, the new content is appended after the existing children. For an example, see the DEMO program below.

Table 27: INSERT^MXMLTMPL - Insert XML in document
Parameter Type Required Description
INSXML Mumps Name Yes Original XML array in which new XML will be inserted
INSNEW Mumps Name Yes XML to insert
INSXPATH String Yes Psuedo-XPATH point at which to do the insertion. See QUERY above for format.

INSINNER^MXMLTMPL(INNXML,INNNEW,INNXPATH)

Like INSERT^MXMLTMPL, except that only the content inside the main tag of the XML in INNNEW is inserted into INNXML. For example, if INNNEW has the following contents:

1 <Book>
2 <Author>Lord Byron</Author>
3 </Book>

Only line 2 gets inserted into the original document INNXML. The outer tags (lines 1 and 3) are discarded. See examples in the DEMO program below.

Table 28: INSINNER^MXMLTMPL - Insert inner XML in document
Parameter Type Required Description
INNXML Mumps Name Yes Original XML array in which new XML will be inserted
INNNEW Mumps Name Yes XML to insert, from which only the inner XML will be inserted.
INNXPATH String Yes Psuedo-XPATH point at which to do the insertion. See QUERY above for format.

Mapping Placeholders

Placeholders are one of the very powerful features of the templating code. Any item in the XML that is enclosed in @@ (like “@@AUTHOR@@”) is a placeholder.

MISSING^MXMLTMPL(IXML,OARY)

This queries IXML for any placeholders that have not been replaced yet (hence the “Missing”) and place the output in a numerically subscripted array OARY. See example below in DEMO program.

Table 29: MISSING^MXMLTMPL - List unreplaced placeholders
Parameter Type Required Description
IXML Mumps Name Yes Input XML
OARY Mumps Name Yes Output in the format OARY(1)="ITEM1",OARY(2)="ITEM2" etc (@@ removed)

MAP^MXMLTMPL(IXML,INARY,OXML)

MAP takes a Mumps Hash in INARY and replaces the hash keys in IXML that are also placeholders with their value, and puts the output in OXML.

Here’s a very simple example:

N KBANIXML,KBANINARY,KBANOXML
S KBANIXML(1)="<Author>@@AUTHOR@@</Author>"
S KBANINARY("AUTHOR")="Lord Byron"
D MAP^MXMLTMPL($NA(KBANIXML),$NA(KBANINARY),$NA(KBANOXML))
W KBANOXML(1),! ; <Author>Lord Byron</Author>

Table 30: MAP^MXMLTMPL - Map placeholders using passed Hash
Parameter Type Required Description
IXML Mumps Name Yes Input XML containing the placeholders to be filled in
INARY Mumps Name Yes Hash in the format of MUMPSNAME("KEY")="VALUE". The key corresponds to the placeholder text in between the @@
OXML Mumps Name Yes Output XML produced by this procedure

Printing for debugging purposes

PARY^MXMLTMPL(GLO,ZN)

Prints an array passed by name in GLO. If optional ZN is passed as -1, line numbers are suppressed. Otherwise, line numbers are printed. See numerous examples in the DEMO program.

Table 31: PARY^MXMLTMPL - Print Array
Parameter Type Required Description
GLO Mumps Name Yes Array to be printed. Doesn't have to be an XML array.
ZN -1 No If -1 is passed, line numbers are not printed; otherwise, line numbers are printed

Advanced functionality for templating

QUEUE^MXMLTMPL(BLST,ARRAY,FIRST,LAST) and BUILD^MXMLTMPL(BLIST,BDEST)

QUEUE and BUILD are to be used together. QUEUE creates build instructions in BLST for items in ARRAY using FIRST and LAST as the instructions on what lines to copy. BUILD executes the instructions in BLIST to create an array in BDEST.

Example (using the reference XML at the beginning of the chapter in array MXMLTEMPLATE):

Starting Array:

>ZWRITE MXMLTEMPLATE
MXMLTEMPLATE(0)=9
MXMLTEMPLATE(1)="<?xml version=""1.0"" encoding=""utf-8"" ?>"
MXMLTEMPLATE(2)="<Books>"
MXMLTEMPLATE(3)="<LastUpdated date=""@@LASTUP@@"" />"
MXMLTEMPLATE(4)="<Book>"
MXMLTEMPLATE(5)="<Author>@@AUTHOR@@</Author>"
MXMLTEMPLATE(6)="<Title>@@TITLE@@</Title>"
MXMLTEMPLATE(7)="<Description>@@DES@@</Description>"
MXMLTEMPLATE(8)="</Book>"
MXMLTEMPLATE(9)="</Books>"

Code:

>D QUEUE^MXMLTMPL($NA(MXMLBLIST),$NA(MXMLTEMPLATE),1,2)

>D QUEUE^MXMLTMPL($NA(MXMLBLIST),$NA(MXMLTEMPLATE),4,4)

>D QUEUE^MXMLTMPL($NA(MXMLBLIST),$NA(MXMLTEMPLATE),8,9)

>ZWRITE MXMLBLIST
MXMLBLIST(0)=3
MXMLBLIST(1)="MXMLTEMPLATE;1;2"
MXMLBLIST(2)="MXMLTEMPLATE;4;4"
MXMLBLIST(3)="MXMLTEMPLATE;8;9"

>D BUILD^MXMLTMPL($NA(MXMLBLIST),$NA(MXMLOUTPUT))

>ZWRITE MXMLOUTPUT
MXMLOUTPUT(0)=5
MXMLOUTPUT(1)="<?xml version=""1.0"" encoding=""utf-8"" ?>"
MXMLOUTPUT(2)="<Books>"
MXMLOUTPUT(3)="<Book>"
MXMLOUTPUT(4)="</Book>"
MXMLOUTPUT(5)="</Books>"

[$$]TRIM^MXMLTMP1(THEXML)

Trim is used to remove elements with no text inside of them. For example, <Author></Author> gets deleted.

It has the following limitations:

Table 32: TRIM^MXMLTMP1 - Trim XML
Parameter Type Required Description
THEXML Mumps Name Yes XML to be trimmed. Trimming is done in place, so you get your XML back in the same location.
Return Value Integer No 0 for no trim happening, 1 for trim happening

Example:

TRIM2 ; - Trim an XML array
 N MXMLARR0
 D PUSH^MXMLTMP1($NA(MXMLARR0),"")
 D PUSH^MXMLTMP1($NA(MXMLARR0),"")
 D PUSH^MXMLTMP1($NA(MXMLARR0),"Pride and Prejudice")
 D PUSH^MXMLTMP1($NA(MXMLARR0),"")
 D PUSH^MXMLTMP1($NA(MXMLARR0),"")
 D PUSH^MXMLTMP1($NA(MXMLARR0),"")
 D PUSH^MXMLTMP1($NA(MXMLARR0),"")
 D PUSH^MXMLTMP1($NA(MXMLARR0),"")
 D TRIM^MXMLTMP1($NA(MXMLARR0))
 ZWRITE MXMLARR0
 QUIT
 ;
 ; MXMLARR0(0)=5
 ; MXMLARR0(1)=""
 ; MXMLARR0(2)=""
 ; MXMLARR0(3)="Pride and Prejudice"
 ; MXMLARR0(4)=""
 ; MXMLARR0(5)="

Demo Program for Templating

DEMO	; Demo program.
	;
CREATE ; Create Template
	N MXMLTEMPLATE
	D PUSH^MXMLTMP1($NA(MXMLTEMPLATE),$$XMLHDR^MXMLUTL())
	D PUSH^MXMLTMP1($NA(MXMLTEMPLATE),"<Books>")
	D PUSH^MXMLTMP1($NA(MXMLTEMPLATE),"<LastUpdated date=""@@LASTUP@@"" />")
	D PUSH^MXMLTMP1($NA(MXMLTEMPLATE),"<Book>")
	D PUSH^MXMLTMP1($NA(MXMLTEMPLATE),"<Author>@@AUTHOR@@</Author>")
	D PUSH^MXMLTMP1($NA(MXMLTEMPLATE),"<Title>@@TITLE@@</Title>")
	D PUSH^MXMLTMP1($NA(MXMLTEMPLATE),"<Description>@@DES@@</Description>")
	D PUSH^MXMLTMP1($NA(MXMLTEMPLATE),"</Book>")
	D PUSH^MXMLTMP1($NA(MXMLTEMPLATE),"</Books>")
	;
PARY1 ; Print Array
	W "Printing pushed template",!
	D PARY^MXMLTMPL($NA(MXMLTEMPLATE))
	;
	; 1 <?xml version="1.0" encoding="utf-8" ?>
	; 2 <Books>
	; 3 <LastUpdated date="@@LASTUP@@" />
	; 4 <Book>
	; 5 <Author>@@AUTHOR@@</Author>
	; 6 <Title>@@TITLE@@</Title>
	; 7 <Description>@@DES@@</Description>
	; 8 </Book>
	; 9 </Books>
	;
MISS1 ; Print elements needing to be resolved
	N MXMLMISS
	D MISSING^MXMLTMPL($NA(MXMLTEMPLATE),$NA(MXMLMISS))
	;
PARY11 ; Print Array
	W "Printing unresolved placeholder elements",!
	D PARY^MXMLTMPL($NA(MXMLMISS))
	K MXMLMISS
	;
	; 1 LASTUP
	; 2 AUTHOR
	; 3 TITLE
	; 4 DES
	;
MAP1 ; Map the Date
	N DATE S DATE=$$FMTE^XLFDT($$NOW^XLFDT())
	N MXMLHASH S MXMLHASH("LASTUP")=DATE
	K DATE
	;
	N MXMLOUTPUT
	D MAP^MXMLTMPL($NA(MXMLTEMPLATE),$NA(MXMLHASH),$NA(MXMLOUTPUT))
	K MXMLHASH
	;
PARY2 ; Print Array
	W !
	W "Printing template with mapped date",!
	D PARY^MXMLTMPL($NA(MXMLOUTPUT))
	;
	; 1 <?xml version="1.0" encoding="utf-8" ?>
	; 2 <Books>
	; 3 <LastUpdated date="Aug 01, 2013@10:43:36" />
	; 4 <Book>
	; 5 <Author>@@AUTHOR@@</Author>
	; 6 <Title>@@TITLE@@</Title>
	; 7 <Description>@@DES@@</Description>
	; 8 </Book>
	; 9 </Books>
	;
	W !
	W "Original: ",!
	D PARY^MXMLTMPL($NA(MXMLTEMPLATE))
	;
	; 1 <?xml version="1.0" encoding="utf-8" ?>
	; 2 <Books>
	; 3 <LastUpdated date="@@LASTUP@@" />
	; 4 <Book>
	; 5 <Author>@@AUTHOR@@</Author>
	; 6 <Title>@@TITLE@@</Title>
	; 7 <Description>@@DES@@</Description>
	; 8 </Book>
	; 9 </Books>
	;
SWAP ; Swap the output into the original
	K MXMLTEMPLATE
	M MXMLTEMPLATE=MXMLOUTPUT
	K MXMLOUTPUT
	;
QUERY1 ; Grab the books parts to use as a repeating segment
	N MXMLBOOKSXML
	D QUERY^MXMLTMPL($NA(MXMLTEMPLATE),"//Books/Book",$NA(MXMLBOOKSXML))
	;
PARY3 ; Print Array
	W !,"Printing the Books XML segement",!
	D PARY^MXMLTMPL($NA(MXMLBOOKSXML))
	;
	; 1 <Book>
	; 2 <Author>@@AUTHOR@@</Author>
	; 3 <Title>@@TITLE@@</Title>
	; 4 <Description>@@DES@@</Description>
	; 5 </Book>
	;
MAP3 ; Make second map
	N MXMLHASH
	S MXMLHASH("AUTHOR")="Lord Byron"
	S MXMLHASH("TITLE")="Don Juan"
	S MXMLHASH("DES")="A swipe at the traditional Don Juan story, the hero goes clueless into various adventures and many romantic conquests"
	N MXMLOUTPUTLB
	D MAP^MXMLTMPL($NA(MXMLBOOKSXML),$NA(MXMLHASH),$NA(MXMLOUTPUTLB))
	K MXMLHASH
	;
PARY4 ; Print Array
	W !,"Printing Mapped Book segment",!
	D PARY^MXMLTMPL($NA(MXMLOUTPUTLB))
	;
	; 1 <Book>
	; 2 <Author>Lord Byron</Author>
	; 3 <Title>Don Juan</Title>
	; 4 <Description>A swipe at the traditional Don Juan story, the hero goes clueless into various adventures and many romantic conquests</
	; Description>
	; 5 </Book>
	;
REPLACE1 ; Replace the original Books segment with the new segment
	D REPLACE^MXMLTMPL($NA(MXMLTEMPLATE),$NA(MXMLOUTPUTLB),"//Books/Book")
	K MXMLOUTPUT
	;
PARY5 ; Print Array
	W !,"Printing original template after mapped segment is inserted",!
	D PARY^MXMLTMPL($NA(MXMLTEMPLATE))
	;
	; 1 <?xml version="1.0" encoding="utf-8" ?>
	; 2 <Books>
	; 3 <LastUpdated date="Aug 01, 2013@10:43:36" />
	; 4 <Book>
	; 5 <Author>Lord Byron</Author>
	; 6 <Title>Don Juan</Title>
	; 7 <Description>A swipe at the traditional Don Juan story, the hero goes clueless into various adventures and many romantic conquests</
	; Description>
	; 8 </Book>
	; 9 </Books>
	;
MAP4 ; Make another book map
	N MXMLHASH
	S MXMLHASH("AUTHOR")="Samuel Butler"
	S MXMLHASH("TITLE")="The way of all Flesh"
	S MXMLHASH("DES")="A semi-autobiographical novel which attacks Victorian-era hypocrisy."
	N MXMLOUTPUTSB
	D MAP^MXMLTMPL($NA(MXMLBOOKSXML),$NA(MXMLHASH),$NA(MXMLOUTPUTSB))
	K MXMLHASH
	;
PARY6 ; Print Array
	W !,"Printing Mapped Book segment",!
	D PARY^MXMLTMPL($NA(MXMLOUTPUTSB))
	;
	; 1 <Book>
	; 2 <Author>Samuel Butler</Author>
	; 3 <Title>The way of all Flesh</Title>
	; 4 <Description>A semi-autobiographical novel which attacks Victorian-era hypocrisy.</Description>
	; 5 </Book>
	;
INSINN1 ; Insert inner portion of Books XML before the end of the Books section
	D INSINNER^MXMLTMPL($NA(MXMLTEMPLATE),$NA(MXMLOUTPUTSB),"//Books/Book")
	;
PARY7 ; Print Array
	W !,"Printing original template after second mapped section is inserted",!
	D PARY^MXMLTMPL($NA(MXMLTEMPLATE))
	W !,"Incorrect XML produced",!
	;
	; 1 <?xml version="1.0" encoding="utf-8" ?>
	; 2 <Books>
	; 3 <LastUpdated date="Aug 01, 2013@10:43:36" />
	; 4 <Book>
	; 5 <Author>Lord Byron</Author>
	; 6 <Title>Don Juan</Title>
	; 7 <Description>A swipe at the traditional Don Juan story, the hero goes clueless into various adventures and many romantic conquests</
	; Description>
	; 8 <Author>Samuel Butler</Author>
	; 9 <Title>The way of all Flesh</Title>
	; 10 <Description>A semi-autobiographical novel which attacks Victorian-era hypocrisy.</Description>
	; 11 </Book>
	; 12 </Books>
	; Incorrect XML produced
	;
DEL1 ; Delete Books section
	D REPLACE^MXMLTMPL($NA(MXMLTEMPLATE),"","//Books/Book")
	;
PARY8 ; Print Array
	W !,"Printing a template without the books section which just got deleted."
	D PARY^MXMLTMPL($NA(MXMLTEMPLATE))
	;
	; 1 <?xml version="1.0" encoding="utf-8" ?>
	; 2 <Books>
	; 3 <LastUpdated date="Aug 01, 2013@10:43:36" />
	; 4 <Book>
	; 5 </Book>
	; 6 </Books>
	;
	W !,"Printing both mapped arrays",!
	D PARY^MXMLTMPL($NA(MXMLOUTPUTLB))
	D PARY^MXMLTMPL($NA(MXMLOUTPUTSB))
	;
	; 1 <Book>
	; 2 <Author>Lord Byron</Author>
	; 3 <Title>Don Juan</Title>
	; 4 <Description>A swipe at the traditional Don Juan story, the hero goes clueless into various adventures and many romantic conquests</
	; Description>
	; 5 </Book>
	; 1 <Book>
	; 2 <Author>Samuel Butler</Author>
	; 3 <Title>The way of all Flesh</Title>
	; 4 <Description>A semi-autobiographical novel which attacks Victorian-era hypocrisy.</Description>
	; 5 </Book>
	;
INSINN2 ; Insert inner portion of Books XML again of Byron's Don Juan
	D INSINNER^MXMLTMPL($NA(MXMLTEMPLATE),$NA(MXMLOUTPUTLB),"//Books/Book")
	;
PARY9 ; Print Array
	W !!,"Printing template with Don Juan"
	D PARY^MXMLTMPL($NA(MXMLTEMPLATE))
	;
	; 1 <?xml version="1.0" encoding="utf-8" ?>
	; 2 <Books>
	; 3 <LastUpdated date="Aug 01, 2013@10:43:36" />
	; 4 <Book>
	; 5 <Author>Lord Byron</Author>
	; 6 <Title>Don Juan</Title>
	; 7 <Description>A swipe at the traditional Don Juan story, the hero goes clueless into various adventures and many romantic conquests</
	; Description>
	; 8 </Book>
	; 9 </Books>
	;
INSERT1 ; Insert all of the Butler's Way of all Flesh into template under Books
	D INSERT^MXMLTMPL($NA(MXMLTEMPLATE),$NA(MXMLOUTPUTSB),"//Books")
	;
PARY0 ; Print Array
	W !!,"Printing template with both books in it"
	D PARY^MXMLTMPL($NA(MXMLTEMPLATE))
	;
	; 1 <?xml version="1.0" encoding="utf-8" ?>
	; 2 <Books>
	; 3 <LastUpdated date="Aug 01, 2013@10:43:36" />
	; 4 <Book>
	; 5 <Author>Lord Byron</Author>
	; 6 <Title>Don Juan</Title>
	; 7 <Description>A swipe at the traditional Don Juan story, the hero goes clueless into various adventures and many romantic conquests</
	; Description>
	; 8 </Book>
	; 9 <Book>
	; 10 <Author>Samuel Butler</Author>
	; 11 <Title>The way of all Flesh</Title>
	; 12 <Description>A semi-autobiographical novel which attacks Victorian-era hypocrisy.</Description>
	; 13 </Book>
	; 14 </Books>
QUIT QUIT

Entity Catalog

The entity catalog is used to store external entities and their associated public identifiers. When the XML parser encounters an external entity reference with a public identifier, it first looks for that public identifier in the entity catalog. If it finds the entity, it retrieves its value. Otherwise, it attempts to retrieve the entity value using the system identifier. The problem with using system identifiers is that they often identify resources that may have been relocated since the document was authored. (This is analogous to the problem with broken links in HTML documents.) Using public identifiers and an entity catalog allows one to build a collection of commonly used and readily accessible external entities (e.g., external document type definitions).

XML ENTITY CATALOG (#950) The entity catalog is a VA FileMan-compatible file that is very simple in structure:

Table 16: XML ENTITY CATALOG file (#950)—Stores external entities and assoc public identifiers
Field # Field Name Datatype Description
.01 ID Free text (1-250) The public identifier associated with this entity.
1 VALUE Word Processing The text associated with the entity.

Unit Tests

Unit tests are provided in routines

In addition, a manual test routine for the XML Parser is at MXMLTEST.