Chapter 5 Generates XML elements

Generating XML elements

If you start the RootElement of a document with RootElement(), you are responsible for generating each element within that RootElement. There are three options:

Generating objects as elements

Output can be generated as elements from InterSystems IRIS objects. In this case, you use the object() method, which writes xmL-enabled objects. The output includes all object references contained in the object. You can specify the name of this element or use the default value defined in the object.

The object() method can only be used between RootElement() and EndRootElement() methods.

This example generates output for all saved instances of a given XML-enabled class:

/// desc: output table data to local file
/// w ##class(PHA.TEST.Xml).WriteAll("Sample.Person")
ClassMethod WriteTableAllToXml(cls As %String = "", directory As %String = "E:\temp\") { if '##class(%Dictionary.CompiledClass).%ExistsId(cls) { Write ! ,"Class does not exist or is not compiled" Quit } s check=$classmethod(cls, "%Extends","%XML.Adaptor") If 'check { Write ! ,"Class does not extend % xml.adaptor" Quit } s filename = directory_"Person"_".xml" s writer = ##class(%XML.Writer).%New() s writer.Indent=1 s status = writer.OutputToFile(filename) if $$$ISERR(status) { do $System.Status.DisplayError(status) quit } s status=writer.RootElement("SampleOutput") if $$$ISERR (status) {do $System. The status. The DisplayError (status) quit} / / for a given object ID s STMT = class scope ##class(%SQL.Statement).%New() s status = stmt.%PrepareClassQuery(cls,"Extent") if $$$ISERR(status) { do $System.Status.DisplayError(status) quit } s rset = stmt.%Execute() while (rset.%Next()) { // For each ID, write the object set objid = rset.%Get("ID") set obj = $CLASSMETHOD(cls,"%OpenId",objid) set status = writer.Object(obj) if $$$ISERR(status) {Do $System.Status.DisplayError(status) Quit}} d writer.EndRootElement() d writer.EndDocument() q ""}Copy the code

The output of this method contains all the saved objects of the given class nested in the root element. For sample.person, the output is as follows:

<? xml version="1.0" encoding="UTF-8"? > <SampleOutput> <Person> <Name>Tillem,Robert Y.</Name> <SSN>967-54-9687</SSN>
    <DOB>1961-11-27</DOB>
    <Home>
      <Street>3355 First Court</Street>
      <City>Reston</City>
      <State>WY</State>
      <Zip>11090</Zip>
    </Home>
    <Office>
      <Street>4922 Main Drive</Street>
      <City>Newton</City>
      <State>NM</State>
      <Zip>98073</Zip>
    </Office>
    <FavoriteColors>
      <FavoriteColorsItem>Red</FavoriteColorsItem>
    </FavoriteColors>
    <Age>47</Age>
  </Person>
  <Person>
    <Name>Waters,Ed X.</Name>
    <SSN>361-66-2801</SSN>
    <DOB>1957-05-29</DOB>
    <Home>
      <Street>5947 Madison Drive</Street>
...
</SampleOutput>
Copy the code

Manually build elements

To manually construct XML elements. In this case, the element() method is used, which writes the element’s opening tag using the name provided. You can then write content, attributes, and child elements. Use the EndElement() method to indicate the end of an element.

The relevant methods are as follows:

Element()

method Element(tag, namespace As %String) as %Status
Copy the code

Write the start tag. You can provide a Namespace for elements, which is applied only if xmL-enabled classes do not have a value for the Namespace parameter.

WriteAttribute()

method WriteAttribute(name As %String, 
                      value As %String  = "", 
                      namespace As %String, 
                      valueNamespace As %String  = "", 
                      global As %Boolean  = 0) as %Status
Copy the code

Write property. Attribute names and values must be specified. The parameter namespace is the namespace of the attribute name. The valueNamespace argument is the namespace of the property value; Used when the value is defined in the XML schema namespace.

For GLOBAL, specify TRUE if the attribute is GLOBAL in the associated XML schema and therefore should have a prefix.

If you use this method, you must use it directly after Element()(or RootElement()).

WriteChars()

method WriteChars(text) as %Status

Copy the code

Writes a string, performing any necessary escapes to make the string fit as element content. Arguments must be of type %String or %CharacterStream type.

WriteCData()

method WriteCData(text) as %Status
Copy the code

Arguments must be of type %String or %CharacterStream type.

WriteBase64()

method WriteBase64(binary) as %Status
Copy the code

Encodes the specified binary byte as BASE-64 and writes the resulting text to the content of the element. This parameter must be of type %Binary or %BinaryStream.

WriteBinHex()

method WriteBinHex(binary) as %Status
Copy the code

Encodes the specified binary byte to binary and writes the resulting text to the content of the element. This parameter must be of type %Binary or %BinaryStream.

EndElement()

method EndElement(a) as %Status
Copy the code

Ends the element that can be matched.

These methods can only be used between RootElement() and EndRootElement() methods.

Note: The approach described here is designed to enable writing specific pieces of logic to XML documents, but in some cases more control may be required. The % xml.writer class provides an additional method, write(), that you can use to write arbitrary strings. Responsible for ensuring that the result is a well-formed XML document; No validation is provided.

The sample

Here is an example routine:

/// w ##class(Demo.XmlDemo).WriteObjXml()
ClassMethod WriteObjXml(a)
{
 
	set writer=##class(%XML.Writer%).New(a)set writer.Indent=1

	set status=writer.OutputToDevice()
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.StartDocument()
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.RootElement("root")
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.Element("SampleElement")
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.WriteAttribute("Attribute"."12345")
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.Element("subelement")
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.WriteChars("yao")
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.EndElement()
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.Element("subelement")
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.WriteChars("xin")
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.EndElement()
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.EndElement()
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.EndRootElement()
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

	set status=writer.EndDocument()
	if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
	q ""
}
Copy the code
DHC-APP>w ##class(Demo.XmlDemo).WriteObjXml()
<?xml version="1.0" encoding="UTF-8"? > <root> <SampleElement Attribute="12345">
    <subelement>yao</subelement>
    <subelement>xin</subelement>
  </SampleElement>
</root>
Copy the code

Use % XMLL. Element

In the previous section, we used Element() and specified the Element to generate; We can also specify namespaces. In some cases, an instance of % xml. Element is used in a class instead of the Element name. This class has the following properties:

  • The Local attribute specifies whether this element is a Local element of its parent, which affects namespace control.
  • The Namespace attribute specifies the Namespace for this element.
  • The Tagname attribute specifies the name of this element.

You can also use the WriteAttribute() method described earlier.