Chapter 9 imports XML into objects

This chapter describes how to import XML documents into IRIS objects using % xml. Reader.

Note: The XML declaration of any XML document used should indicate the character encoding of the document, and the document should be encoded as declared. If character encodings are not declared, IRIS will use the default values described earlier in “Input and output character encodings.” If these defaults are incorrect, modify the XML declaration so that it specifies the actual character set to use.

You can also use % xml. Reader to read any XML document and return the DOM(Document Object Model).

Create an XML reader overview

IRIS provides tools for reading XML documents and creating one or more instances of XML-enabled IRIS objects that correspond to the elements of that document. Basic requirements are as follows:

  • The class definition of this object must be extended%XML.Adaptor. With a few exceptions, the class referenced by the object must also be extended%XML.Adaptor.

Tip: If the corresponding XML schema is available, you can use it to generate classes (and any supported classes).

  • To import the XML document, create%XML.Reader, and then calls the methods of that instance. These methods specify XML source documents, associate XML elements with XML-enabled classes, and read elements from the source into objects.

% xml. Reader uses the methods provided by % xml. Adaptor in the class to do the following:

  • It uses the InterSystems IRIS SAX interface to parse and validate incoming XML documents. Validation can include DTD or XML schema validation.
  • It determines whether any XML-enabled objects are associated with elements contained in the XML document and creates in-memory instances of those objects when the document is read.

Please note that,%XML.ReaderThe created object instances are not stored in the database; They are objects in memory. If you want to store an object in a database, you must either call the %Save() method (for persistent objects) or copy the associated attribute value to the persistent object and Save it. The application must also decide when to insert new data and when to update existing data;%XML.ReaderThis distinction cannot be made.

The terminal session below shows a simple example. Here, we read the XML file into a new object, examine the object, and save the object:


/// w ##class(PHA.TEST.Xml).ReadXml()
ClassMethod ReadXml(a)
{
	Set reader = ##class(%XML.Reader%).New(a)Set file="E:\temp\samplePerson.xml"
	Set status = reader.OpenFile(file)
	if $$$ISERR(status) { do $System.Status.DisplayError(status) quit }
	Write status,!
	Do reader.Correlate("Person"."Sample.Person")
	Do reader.Next(.object,.status)
	if $$$ISERR(status) { do $System.Status.DisplayError(status) quit }
	Write object.Name,!

	Do object.%Save()
	q ""
}
Copy the code

This example uses the following sample XML file:

<Person GroupID="90455">
  <Name>Worthington,Jeff R.</Name>
  <DOB>1976-11-03</DOB>
  <Address>
    <City>Elm City</City>
    <Zip>27820</Zip>
  </Address>
  <Doctors>
    <Doctor>
      <Name>Best,Nora A.</Name>
    </Doctor>
    <Doctor>
      <Name>Weaver,Dennis T.</Name>
    </Doctor>
  </Doctors>
</Person>
Copy the code

Creating an import method

Overall method structure

Methods should perform some or all of the following operations in the following order:

  1. create%XML.ReaderThe instance.
  2. This instance can also be specifiedFormatProperty to specify the format of the file to import.

By default, InterSystems IRIS assumes that XML files are in literal format. If the file is SOAP encoded, you must specify this so that the file can be read correctly.

  1. You can optionally set additional properties for this instance.
  2. Please use the%XML.ReaderOne of the following methods
  • OpenFile()– Open the file.
  • OpenStream()– Open a stream.
  • OpenString()– Opens a string.
  • OpenURL()– Open a URL.

In each case, you can optionally specify a second parameter to the method to override the value of the Format attribute.

  1. Associate one or more XML element names in this file with classes that support InterSystems IRIS XML with the appropriate structure.

There are two ways to do this:

  • useCorrelate()Method, which has the following signature:
method Correlate(element As %String, 
                 class As %String, 
                 namespace As %String)
Copy the code

Where Element is the XML element name, class is the InterSystems IRIS class name (with package), and namespace is the optional namespace URI.

If the namespace parameter is used, the match is limited to the specified element name in the specified namespace. If the namespace argument is specified as “”, it matches the default namespace given in the Next() method. If the namespace parameter is not used, only the element name is used for matching.

Tip: The Correlate() method can be repeatedly called to Correlate multiple elements.

  • useCorrelateRoot()Method, which has the following signature:
method CorrelateRoot(class As %String)
Copy the code

Where class is the InterSystems IRIS class name (with package). This method specifies that the root element of the XML document is associated with the specified class.

  1. Instantiate a class instance as follows:

If you use Correlate(), you loop over related elements in the file, one element at a time. In the loop, use the Next() method, which has the following signature:

method Next(ByRef oref As %ObjectHandle, 
            ByRef sc As %Status, 
            namespace As %String = "") as %Integer
Copy the code

OREF is the object created by this method, SC is the state, and Namespace is the default Namespace for files.

  • If you are usingCorrelateRoot(), please callnext()Method once, which causes the related class to be instantiated.

The Next() method returns 0 when the end of the file is reached. If you call next() again after that, you loop through the objects in the file again, starting at the top of the file. (The specified association is still valid.)

Error checking

Most of the methods mentioned in the previous section return state. You should check the status after each step and exit if appropriate.

Basic import Example

The following XML file named test.xml:

<Root>
   <Person>
      <Name>yao</Name>
   </Person>
   <Person>
      <Name>xin</Name>
   </Person>
</Root>
Copy the code

Let’s start by defining an XML-enabled class myapp. Person, which is an object representation of Person:

Class MyApp.Person Extends (%Persistent, %XML.Adaptor)
{

Parameter XMLNAME = "Person";

Property Name As %String;

Storage Default
{
<Data name="PersonDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Name</Value>
</Value>
</Data>
<DataLocation>^MyApp.PersonD</DataLocation>
<DefaultData>PersonDefaultData</DefaultData>
<IdLocation>^MyApp.PersonD</IdLocation>
<IndexLocation>^MyApp.PersonI</IndexLocation>
<StreamLocation>^MyApp.PersonS</StreamLocation>
<Type>%Library.CacheStorage</Type>
}

}


Copy the code

To import this file into an instance of the MyAppPerson class, we can write the following method:

/// w ##class(PHA.TEST.Xml).ImportXml()
ClassMethod ImportXml(a)
{
    // Create an instance of % xml.reader
    Set reader = ##class(%XML.Reader%).New() // Start processing filesSet status = reader.OpenFile("E:\temp\testPerson.xml")
    If $$$ISERR(status) {do $System.Status.DisplayError(status)}

    // Associate the class name with the XML element name
    Do reader.Correlate("Person"."MyApp.Person")
    
    // Read objects from an XML file
    While (reader.Next(.object,.status)) {
        Write object.Name,!
    }
    
    // If an error is found during processing, it is displayed
    If $$$ISERR(status) {do $System.Status.DisplayError(status)}
    q ""
}
Copy the code
DHC-APP>w ##class(PHA.TEST.Xml).ImportXmlYao xin ()Copy the code

This method performs several tasks:

  • It uses InterSystems IRISSAXThe interface parses input files. This includes validating documents against their DTD or schema, if specified.
  • Correlate()Methods the classMyAppStudent: Relate.

MyPerson and the XML element ; Each child element in becomes an attribute of MyPerson.

  • It reads each from the input file<Person>Element until there are no more elements left.
  • Finally, if the loop is terminated by an error, the error is displayed on the current output device.

As mentioned above, this example does not store objects to a database. Because MyPerson is a persistent object, you can do this by adding the following line to the While loop:

/// w ##class(PHA.TEST.Xml).ImportXml()
ClassMethod ImportXml(a)
{
    // Create an instance of % xml.reader
    Set reader = ##class(%XML.Reader%).New() // Start processing filesSet status = reader.OpenFile("E:\temp\testPerson.xml")
    If $$$ISERR(status) {do $System.Status.DisplayError(status)}

    // Associate the class name with the XML element name
    Do reader.Correlate("Person"."MyApp.Person")
    
    // Read objects from an XML file
    While (reader.Next(.object,.status)) {
        Write object.Name,!
		Set savestatus = object.%Save()
		If $$$ISERR(savestatus) {do $System.Status.DisplayError(savestatus)}
    }
    
    // If an error is found during processing, it is displayed
    If $$$ISERR(status) {do $System.Status.DisplayError(status)}
    

    q ""
}

Copy the code

Access documents using HTTPS urls

For the OpenURL() method, if the document is at a URL that requires SSL/TLS, do the following:

  1. Use the administrative portal to create aSSL/TLSConfiguration. This is a one-time step.
  2. use%XML.Reader, set the reader instance’sSSLConfigurationProperties. For this value, specify the name of the SSL/TLS configuration created in the previous step.

Alternatively, when using % xml. Reader, you can do the following:

  1. create%Net.HttpRequestInstance.
  2. Place the instance’sSSLConfigurationProperty is set to be equal to that created in the MANAGEMENT portalSSL/TLSConfiguration name of the configuration.
  3. use%Net.HttpRequestAs an example ofOpenURL()The third parameter of.

Such as:

Class YX.Config Extends (%Persistent, %XML.Adaptor)
{

Parameter XMLNAME = "update";

Property version As %String;

Property name As %String;

Property url As %String;
}
Copy the code
/// request HTTP XML to be mapped to the local class
/ / / w # # class (PHA) TEST) Xml). ReadXmlHttp (" http://192.168.10.3/dthealth/web/csp/version.xml ")
ClassMethod ReadXmlHttp(url)
{
	set reader = ##class(%XML.Reader%).New(a)set request = # #class(%Net.HttpRequest%).New(a)set request.SSLConfiguration="yx" 
	set status = reader.OpenURL(url,,request)
	If $$$ISERR(status) {do $System.Status.DisplayError(status)}
	
    // Associate the class name with the XML element name
    Do reader.Correlate("update"."YX.Config")
	
    While (reader.Next(.object,.status)) {
		Write object.version,!
		Write object.name,!
		Write object.url,!
    }
	q ""
}
Copy the code
DHC-APP>w ##class(PHA.TEST.Xml).ReadXmlHttp("http: / / 192.168.10.3 /dthealth/web/csp/version.xml27 ")Herb
http: / / 192.168.31.124 /dthealth/web/csp/Herb.apk
Copy the code

Access documents when the server requires authentication

Create authentication if the server requires it%Net.HttpRequestAnd sets the username and password properties for that instance. You can also use SSL as described above (hence the SettingsSSLConfigurationProperties). Then use the%Net.HttpRequestAs an example ofOpenURL()The third parameter to the