what would cause xmlreader to skip an element
Importing XML into Caché Objects
This topic describes how to use the %XML.Reader class to import XML documents into Caché objects. It discusses the following items:
-
An overview and a simple case
-
How to create an import method and the basic construction of such a method, with an case
-
How to bank check for required elements and attributes
-
How to handle unexpected elements and attributes
-
How to handle empty elements and attributes
-
How to skip before parts of the input document
-
Other methods that you use less frequently
-
Other backdrop that you can set to control the overall behavior of the reader
-
How to customize how the reader behaves when information technology finds a correlated object
-
Boosted examples
Note:
The XML declaration of any XML document that you use should indicate the character encoding of that document, and the document should exist encoded equally declared. If the character encoding is not declared, Caché uses the defaults described in "Character Encoding of Input and Output," earlier in this book. If these defaults are not correct, change the XML declaration so that it specifies the grapheme set up actually used.
You can too utilise %XML.Reader to read an arbitrary XML document and return a DOM (Document Object Model); see the topic "Representing an XML Document as a DOM," later in this book.
Overview of Creating an XML Reader
Caché provides tools for reading an XML document and creating one or more than instances of XML-enabled Caché objects that stand for to elements of that document. The essential requirements are every bit follows:
-
The course definition for that object must extend %XML.Adaptor
. With a few exceptions, the classes to which that object refers must also extend %XML.Adaptor
. See Projecting Objects to XML.
Tip:
If the respective XML schema is available, yous can use that to generate the course (and whatever supporting classes). Come across the topic "Generating Classes from XML Schemas," later in this book.
-
To import the XML document, create an instance of %XML.Reader
and then invoke methods of that instance. These methods specify the XML source document, associate an XML element with an XML-enabled class, and read elements from the source into objects.
The %XML.Reader class works with the methods provided by the %XML.Adaptor
form to exercise the post-obit:
-
It parses and validates the incoming XML document using the Caché SAX interface. The validation can include either DTD or XML Schema validation.
-
It determines if any XML-enabled objects are correlated with the elements contained within the XML document and creates in-memory instances of these objects equally information technology reads the document.
Annotation that the object instances created by %XML.Reader are non stored within the database; they are in-memory objects. If you want to store objects within the database, y'all must call the %Save() method (for persistent objects) or copy the relevant property values to a persistent object and save information technology. The application must too make up one's mind when to insert new information and when to update existing information; %XML.Reader
has no way of making this distinction.
The following Last session shows a simple example. Here nosotros read an XML file into a new object, examine that object, so relieve that object:
GXML>Prepare reader = ##class(%XML.Reader).%New() GXML>Ready file="c:\sample-input.xml" GXML>Ready status = reader.OpenFile(file) GXML>Write condition 1 GXML>Do reader.Correlate("Person","GXML.Person") GXML>Practice reader.Next(.object,.status) GXML>Write status 1 GXML>Write object.Name Worthington,Jeff R. GXML>Write object.Doctors.Count() 2 GXML>Do object.%Save() This example uses the following sample XML file:
< Person GroupID = "90455" > < Proper name > Worthington , Jeff R. </ Name > < DOB > 1976-11-03 </ DOB > < Accost > < Urban center > Elm City </ Urban center > < Aught > 27820 </ Aught > </ Address > < Doctors > < Doctor > < Name > All-time , Nora A. </ Name > </ Doctor > < Doctor > < Name > Weaver , Dennis T. </ Name > </ Doc > </ Doctors > </ Person >
Creating an Import Method
Overall Method Construction
Your method should do some or all of the following, in this club:
-
Create an instance of the %XML.Reader
class.
-
Optionally specify the Format property of this instance, to specify the format of the file that yous are importing; come across "Reader Properties."
By default, Caché assumes that XML files are in literal format. If your file is in Soap-encoded format, you must indicate this then that the file can be read correctly.
-
Optionally gear up other properties of this instance; see "Reader Properties."
-
Open the source. To do and so, use one of the following methods of %XML.Reader
:
-
OpenFile() — Opens a file.
-
OpenStream() — Opens a stream.
-
OpenString() — Opens a cord.
-
OpenURL() — Opens a URL.
If the URL uses HTTPS, see "Accessing a Document at an HTTPS URL," later in this topic.
In each case, you tin can optionally specify a second argument for the method, to override the value of the Format property.
-
-
Correlate 1 or more XML element names in this file with Caché XML-enabled classes that take the corresponding structures. There are two ways to practice this:
-
Use the Correlate() method, which has the following signature:
method Correlate(element As %Cord, class As %String, namespace As %String)
Where element is an XML element name, course is a Caché class proper name (with package), and namespace is an optional namespace URI.
If you use the namespace argument, the match is restricted to the specified element proper noun in the specified namespace. If you specify the namespace argument as "", that matches the default namespace given in the Next() method. If you practice not utilize the namespace argument, and so only the chemical element name is used for the match.
Tip:
Y'all tin can telephone call the Correlate() method repeatedly to correlate more than one element, although the examples in this topic show just ane correlation.
-
Use the CorrelateRoot() method, which has the post-obit signature:
method CorrelateRoot(class As %Cord)
Where class is a Caché grade name (with packet). This method specifies that the root element of the XML document is correlated to the specified form.
-
-
Instantiate the class instances as follows:
-
If you used Correlate(), loop through the correlated elements in the file, one element at a time. Inside the loop, apply the Adjacent() method, which has the following signature:
method Next(ByRef oref Equally %ObjectHandle, ByRef sc As %Status, namespace As %String = "") every bit %Integer
Where oref is the object created by the method, sc is the status, and namespace is the default namespace for the file.
-
If you lot used CorrelateRoot(), phone call the Adjacent() method once, which causes the correlated course to be instantiated.
The Next() method returns 0 when it reaches the end of the file. If you call Side by side() again after this, y'all will loop through the objects in the file over again, starting at the pinnacle of the file. (The correlations you specified are still in effect.)
-
Error Checking
Most of the methods mentioned in the previous section render a status. Yous should bank check the status after each step and quit if advisable.
Basic Import Case
Consider the post-obit XML file chosen test.xml:
< Root > < Person > < Name > Elvis Presley </ Proper name > </ Person > < Person > < Name > Johnny Carson </ Proper name > </ Person > </ Root >
We start past defining an XML-enabled class, MyApp.Person, that is an object representation of a person:
Class MyApp . Person Extends ( %Persistent , %XML . Adaptor ) { Parameter XMLNAME = "Person" ; Holding Name Equally %Cord ; }
To import this file into an instance of a MyAppPerson grade, we could write the post-obit method:
ClassMethod Import () { // Create an instance of %XML.Reader Prepare reader = ##class ( %XML . Reader ) . %New ( ) // Begin processing of the file Set status = reader . OpenFile ( "c:\test.xml" ) If $$$ ISERR ( status ) { do $System . Condition . DisplayError ( status ) } // Associate a class proper name with the XML chemical element name Do reader . Correlate ( "Person" , "MyApp.Person" ) // Read objects from xml file While ( reader . Next ( . object , . status ) ) { Write object . Name , ! } // If error found during processing, show it If $$$ ISERR ( status ) { do $System . Status . DisplayError ( condition ) } }
This method performs several tasks:
-
Information technology parses the input file using the Caché SAX interface. This includes validating the certificate confronting its DTD or schema, if specified.
-
The Correlate() method assembly the grade MyApp.MyPerson with the XML element <Person>; each child element in <Person> becomes a belongings of MyPerson.
-
It reads each <Person> element from the input file until there are none left.
-
Finally, if the loop terminates because of an fault, the error is displayed on the current output device.
Every bit mentioned above, this example does not store objects to the database. Because MyPerson is a persistent object, you could do this by calculation the following lines inside the While loop:
Set savestatus = object . %Save ( ) If $$$ ISERR ( savestatus ) { exercise $System . Status . DisplayError ( savestatus ) }
Accessing a Document at an HTTPS URL
For the OpenURL() method, if the document is at a URL that requires SSL/TLS, practise the post-obit:
-
Use the Management Portal to create an SSL/TLS configuration that contains the details of the needed connection. For data, see the topic "Using SSL/TLS with Caché" in the Caché Security Administration Guide.
This is a one-fourth dimension step.
-
When you use %XML.Reader
, prepare the SSLConfiguration property of the reader case. For the value, specify the name of the SSL/TLS configuration that y'all created in the previous step.
Or, when y'all use %XML.Reader , as well practise the following:
-
Create an case of %Cyberspace.HttpRequest
.
-
Set the SSLConfiguration property of that instance equal to the configuration name of the SSL/TLS configuration that you created in the Management Portal.
-
Apply that instance of %Internet.HttpRequest
as the 3rd statement to OpenURL().
For example:
set reader = ##class ( %XML . Reader ) . %New ( ) ready httprequest = ##form ( %Cyberspace . HttpRequest ) . %New ( ) set httprequest . SSLConfiguration = "mysslconfigname" set condition = reader . OpenURL ( "https://myurl" , , httprequest )
Accessing a Document When the Server Requires Hallmark
If the server requires authentication, create an instance of %Net.HttpRequest and set the Username and Password backdrop of that case. Besides use SSL as described above (and so also set the SSLConfiguration property). Then use that case of %Net.HttpRequest
as the third argument to OpenURL() as shown in the example above.
For more details on %Net.HttpRequest and authentication, see "Providing Login Credentials" in the topic "Sending HTTP Requests" in Using Caché Internet Utilities.
Checking for Required Elements and Attributes
By default, the Side by side() method does not cheque for the existence of elements and attributes that stand for to backdrop that are marked every bit Required. To cause the reader to check for the existence of such elements and attributes, set the CheckRequired property of the reader to i earlier calling Next(). The default value for this property is 0, for compatibility reasons.
If yous ready CheckRequired to ane, and if you call Next() and the imported XML is missing a required element or attribute, the Adjacent() method sets the sc argument to an error code. For instance:
SAMPLES>set adjacent= reader.Side by side(.object,.status) SAMPLES>w next 0 SAMPLES>d $system.Status.DisplayError(status) ERROR #6318: Holding required in XML certificate: ReqProp
Controlling How Empty Elements and Attributes Are Imported
When you XML-enable an object, yous specify how cypher values and empty strings are projected to XML (see Projecting Objects to XML).
One of the options is to set XMLIGNORENULL equal to "RUNTIME" (not case-sensitive) in the XML-enabled class. In this case, when yous use %XML.Reader to read an XML file and create Caché objects, Caché uses the value of the IgnoreNull property of the reader to determine how to handle empty elements or attributes, as follows:
-
If the IgnoreNull belongings of the reader is 0 (the default), and an chemical element or attribute is empty, the respective property is set equal to $char(0)
-
If the IgnoreNull belongings of the reader is 1, and an element or attribute is empty, the corresponding property is not set up and therefore equals ""
The IgnoreNull property of the reader has no effect unless the XMLIGNORENULL is "RUNTIME" in the XML-enabled grade; the other possible values for XMLIGNORENULL are 0 (the default), 1, and "INPUTONLY"; see Projecting Objects to XML.
Example: IgnoreNull Is 0 (Default)
Commencement, consider the following class:
Class EmptyStrings . Import Extends ( %Persistent , %XML . Adaptor ) { Parameter XMLNAME = "Test" ; /// Reader volition fix IgnoreNull property Parameter XMLIGNORENULL = "RUNTIME" ; Property PropertyA As %String ; Property PropertyB As %String ; Property PropertyC As %String ; Property PropertyD As %String ( XMLPROJECTION = "ATTRIBUTE" ) ; Property PropertyE As %Cord ( XMLPROJECTION = "Aspect" ) ; }
Also consider the following XML file:
<? xml version = "one.0" encoding = "UTF-8" ?> < Test PropertyD = "" > < PropertyA > </ PropertyA > < PropertyB xsi:nil = "true" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-case" /> </ Test >
If y'all create an instance of %XML.Reader and apply information technology to import this file into the previous form, you get the post-obit effect:
-
PropertyA and PropertyD equal $char(0).
-
All other backdrop equal "".
For instance, if you wrote a routine to examine each holding, inspect its value, and write output, you might go something like the post-obit:
PropertyA is $char(0) PropertyB is nix PropertyC is cypher PropertyD is $char(0) PropertyE is nil
Instance: IgnoreNull Is 1
In a variation of the preceding case, we set the IgnoreNull property of the reader equal to 1. In this case, all backdrop equal "".
For case, if you wrote a routine to examine each property, inspect its value, and write output, you might get something like the following:
PropertyA is nil PropertyB is null PropertyC is null PropertyD is cipher PropertyE is naught
Skipping Earlier Parts of the Input Document
An XML document consists of a prepare of nodes; the root node is numbered 0, the showtime element inside that is numbered 1, and then on. You can specify the node at which to start reading; this is specially useful for large documents. To do so, set the Node property of the reader. For the value, specify an integer.
An instance method follows:
ClassMethod DemoSkippingAhead ( nodenumber equally %Integer = 0 ) { Set cls = "GXML.Person" Set up filename = "c:\GXML.Person.xml" Set chemical element = "Person" // Create an instance of %XML.Reader Set reader = ##class ( %XML . Reader ) . %New ( ) // Begin processing of the file Set status = reader . OpenFile ( filename ) If $$$ ISERR ( status ) { Do $System . Status . DisplayError ( status ) } // Associate a course name with the XML element name Do reader . Correlate ( element , cls ) //skip ahead in the file Set reader . Node = nodenumber // Read objects from xml file While ( reader . Next ( . object , . condition ) ) { Write "Node number " _ reader . Node _ " contains " _ object . Proper noun , ! } }
This method assumes a specific input file, grade proper name, and element name. By default, this method starts at the beginning of the file. For instance:
GXML>d ##course(Readers.ReadFile).DemoSkippingAhead() Node number 3 contains Emerson,Republic of chad I. Node number xxx contains O'Rielly,Patricia L. Node number 63 contains Hanson,Brendan T. Node number 120 contains Orwell,Tara H. Node number 195 contains Gilt,Elvis O. Node number 234 contains Klein,Brenda U. Node number 252 contains Yezek,Kristen Q. Node number 327 contains Quine,Angelo B. Node number 378 contains Vivaldi,Milhouse J. Node number 453 contains Yezek,Vincent D. Node number 471 contains Xander,Juanita D. Node number 522 contains Winters,Kyra R. Node number 555 contains Woo,Michelle J. Node number 636 contains Ihringer,Yan A. Node number 654 contains W,Hannah N. Node number 729 contains Xiang,Bob G. Node number 762 contains Ximines,Howard H. Node number 789 contains Quixote,Jocelyn P. Node number 864 contains Hills,Charles Due east. Node number 897 contains Evans,Milhouse R.
In contrast, we could skip ahead as follows:
GXML>d ##class(Readers.ReadFile).DemoSkippingAhead(700) Node number 729 contains Xiang,Bob Grand. Node number 762 contains Ximines,Howard H. Node number 789 contains Quixote,Jocelyn P. Node number 864 contains Hills,Charles Eastward. Node number 897 contains Evans,Milhouse R.
Other Useful Methods
On occasion, you may need to use the following additional methods of %XML.Reader :
-
Utilise the Rewind() method if you demand to restart reading from the start of the XML source document. This method clears all correlations.
-
Utilise the Shut() method if you want to explicitly close and clean up the import handler. The import handler is cleaned up automatically; this method is included for backward compatibility.
Reader Properties
Yous can set the following backdrop of %XML.Reader to control the overall behavior of your method:
-
Use the UsePPGHandler property to specify whether the instance of %XML.Reader
uses process-individual globals when it parses the document. If this property is true, the instance uses process-private globals. If this property is simulated, the instance uses memory. If this belongings is non set up (or equals an empty string), the instance uses the default, which is normally memory.
Apply the Format holding to specify the overall format of the XML certificate. Specify one of the post-obit values:
-
"literal", the default, which is used in most of the examples in this topic.
-
"encoded", encoded as described in the SOAP ane.1 standard.
-
"encoded12", encoded as described in the Soap 1.ii standard.
Note that you can override the Format property inside the OpenFile(), OpenStream(), OpenString(), and OpenURL() methods.
This belongings has no effect unless yous use Correlate() and Side by side().
-
-
Use the Summary belongings to force the reader to import simply the summary fields of the XML-enabled objects. Every bit noted in Projecting Objects to XML, the summary of an object is specified by its XMLSUMMARY class parameter, which y'all specify as a comma-separated list of properties.
-
Use the IgnoreSAXWarnings property to specify whether the reader should report warnings issued past the SAX parser.
%XML.Reader likewise provides properties that you lot tin use to examine the document you are reading:
-
The Document holding contains an instance of %XML.Document
that represents the entire, parsed certificate that yous are reading. For information on %XML.Document
, see the class reference.
-
The Node property is a string that represents the current node of the XML document. Notation that 0 ways the certificate, that is, the parent of the root element.
For information on the EntityResolver, SAXFlags, and SAXSchemaSpec properties, come across the topic "Customizing How the SAX Parser Is Used." Note that the SAXMask belongings is ignored.
Redefining How the Reader Handles Correlated Objects
When an instance of %XML.Reader finds an XML element that is correlated to an XML-enabled course, the reader calls the XMLNew() method of that class, which in plow calls %New() by default. That is, when a reader finds a correlated element, it creates a new object of the correlated class. The new object is populated with the information that y'all read from the XML document.
Yous tin can customize this behavior by redefining XMLNew() in your XML-enabled class (or perhaps in your own custom XML adaptor). For case, this method can instead open an existing instance of that class. The existing case then receives the data that you read from the XML document.
The following examples evidence how you can modify XMLNew() to update existing instances with new data from an XML document.
In both examples, for simplicity, we assume that a node in the XML document contains an ID that we can compare to the IDs in the extent for the class. Nosotros could of course compare the XML document to the existing objects in other ways.
When %XML.Reader Calls XMLNew()
For reference, %XML.Reader calls the XMLNew() method automatically in two circumstances:
-
%XML.Reader
calls XMLNew() when you call the Next() method of %XML.Reader
, after you have correlated XML elements (in an external document) with an XML-enabled class. The Side by side() method gets the adjacent element from the certificate, calls XMLNew() to create an case of the appropriate object, and then imports the chemical element into the object.
-
Similarly, %XML.Reader
calls XMLNew() for any object-valued properties of the correlated XML elements.
Example 1: Modifying XMLNew() in an XML-Enabled Grade
First consider the following XML file:
<?xml version="1.0" encoding="UTF-viii"?> <root> <Person> <CacheID>4</CacheID> <Name>Quine,Maria Chiliad.</Name> <DOB>1964-11-14</DOB> <Accost> <City>Hialeah</City> <Naught>94999</Zip> </Accost> <Doctors> <Doctor> <Name>Vanzetti,Debra B.</Name> </Md> </Doctors> </Person> ...
This file maps to the post-obit Caché class (partly shown):
Class GXML . PersonWithXMLNew Extends ( %Persistent , %Populate , %XML . Adaptor ) { Parameter XMLNAME = "Person" ; /// make sure this is the same as the XMLNAME of the property /// in this class that is of type %XML.Id Parameter CACHEID As %String = "CacheID" ; Property IdForExport As %XML . Id ( XMLNAME = "CacheID" , XMLPROJECTION = "ELEMENT" ) [ Individual , Transient ] ; Property Name Equally %Name ; Property DOB As %Date ( FORMAT = 5 , MAXVAL = "+$h" ) ; Property Address Every bit GXML . Address ; Property Doctors As list Of GXML . Doc ; }
In this class, the purpose of the IdForExport property is to project the Caché internal ID to an chemical element (CacheID) when objects of this class are exported. (In this detail case, this enables us to easily generate suitable files for import. Your grade does not take to contain such a property.)
The CACHEID parameter is used to point the element that nosotros use for the Caché ID when we export objects of this class. This is included only for the convenience of the customized XMLNew() method that we take also added to this course. This method is defined as follows:
ClassMethod XMLNew ( md As %XML . Document , node Every bit %Integer , contOref Every bit %RegisteredObject = "" ) Every bit GXML . PersonWithXMLNew { Set up id = "" Set tmpnode = doc . GetNode ( node ) Do tmpnode . MoveToFirstChild ( ) Do { //compare data node to the string given past the CACHEID parameter //which indicates the XMLNAME of the ids for this object If tmpnode . NodeData = .. # CACHEID { //become the text from this node; this corresponds to an id in Cache Do tmpnode . GetText ( . id ) } } While tmpnode . MoveToNextSibling ( ) //if at that place is no id in the given node, create a new object If id = "" { Write ! , "Creating a new object..." Quit .. %New ( ) } //open up the given object Set result = .. %OpenId ( id ) //if the id doesn't stand for to an existing object, create a new object If consequence = $$$ NULLOREF { Write ! , "Creating a new object..." Quit .. %New ( ) } Write ! , "Updating an existing object..." Quit event }
%XML.Reader calls this method when it reads an XML certificate and correlates a node to GXML.PersonWithXMLNew. This method looks at the value of the CACHEID parameter in this class, which is CacheID. It then examines the node in the document with the element CacheID and gets its value.
If this ID corresponds to an existing object of this class, the method opens that instance. Otherwise, the method opens a new instance of this class. In both cases, the example receives the properties as specified in the XML certificate.
Finally, the following utility class includes a method that opens the XML file and calls %XML.Reader :
Course GXML . DemoXMLNew Extends %RegisteredObject { ClassMethod ReadFile ( filename As %String = "c:\temp\sample.xml" ) { Set up reader = ##class ( %XML . Reader ) . %New ( ) Set sc = reader . OpenFile ( filename ) If $$$ ISERR ( sc ) { Practice $system . OBJ . DisplayError ( sc ) Quit } Do reader . Correlate ( "Person" , "GXML.PersonWithXMLNew" ) //loop through elements in file While reader . Next ( . person , . sc ) { Write ! , person . Proper noun , ! Set sc = person . %Save ( ) If $$$ ISERR ( sc ) { Practise $organization . OBJ . DisplayError ( sc ) Quit } } Quit } }
When you run the preceding method, one of the post-obit occurs for each <Person> chemical element in the file:
-
An existing object is opened, updated with details from the file, and saved.
-
Or a new object is created, with details from the file.
For example:
GXML>d ##class(GXML.DemoXMLNew).ReadFile() Updating an existing object... Zampitello,Howard I. Creating a new object... Smyth,Linda D. Creating a new object... Vanzetti,Howard I.
Case 2: Modifying XMLNew() in a Custom XML Adaptor
In the second example, we create a custom XML adaptor to perform the same actions as shown in the first example. The adaptor course is equally follows:
Class GXML . AdaptorWithXMLNew Extends %XML . Adaptor { /// make sure this is the same every bit the XMLNAME of the property in this class /// that is of type %XML.Id Parameter CACHEID As %String = "CacheID" ; Property IdForExport Equally %XML . Id ( XMLNAME = "CacheID" , XMLPROJECTION = "ELEMENT" ) [ Individual , Transient ] ; ClassMethod XMLNew ( document As %XML . Document , node As %Integer , containerOref Every bit %RegisteredObject = "" ) As %RegisteredObject [ CodeMode = objectgenerator, GenerateAfter = %XMLGenerate , ServerOnly = 1] { If %compiledclass . Name '= "GXML.AdaptorWithXMLNew" { Do %code . WriteLine ( " Set id=""""" ) Practice %code . WriteLine ( " Set tmpnode=document.GetNode(node)" ) Do %code . WriteLine ( " Do tmpnode.MoveToFirstChild()" ) Do %code . WriteLine ( " Do {" ) Exercise %code . WriteLine ( " If tmpnode.NodeData=..#CACHEID " ) Do %code . WriteLine ( " {Practice tmpnode.GetText(.id)}" ) Practice %code . WriteLine ( " } While tmpnode.MoveToNextSibling() " ) Do %code . WriteLine ( " If id="""" {" ) Practise %code . WriteLine ( " Write !,""Creating new object...""" ) Do %code . WriteLine ( " Quit ##class(" _ %class . Proper noun _ ").%New()}" ) Do %lawmaking . WriteLine ( " set issue=##class(" _ %class . Proper name _ ").%OpenId(id)" ) Do %lawmaking . WriteLine ( " If result=$$$NULLOREF {" ) Do %code . WriteLine ( " Write !,""Creating new object...""" ) Do %code . WriteLine ( " Quit ##class(" _ %class . Name _ ").%New() }" ) Exercise %lawmaking . WriteLine ( " Write !,""Updating existing object ...""" ) Do %code . WriteLine ( " Quit outcome" ) } QUIT $$$ OK } }
The IdForExport property and the CACHEID parameter establish a convention for how we project the Caché internal ID to an element when objects of subclasses are exported. The intent is that if y'all redefine IdForExport in a subclass, you redefine CACHEID correspondingly.
In this class, the XMLNew() method is a method generator. When this form (or any subclass) is compiled, Caché writes the code shown here into the body of this method. Meet the topic "Method Generators" in Using Cache Objects.
The following form extends our custom adaptor:
Form GXML . PersonWithXMLNew2 Extends ( %Persistent , %Populate , GXML . AdaptorWithXMLNew ) { Parameter XMLNAME = "Person" ; Property Proper name As %Proper name ; Property DOB As %Engagement ( FORMAT = v , MAXVAL = "+$h" ) ; Holding Address As GXML . Address ; Holding Doctors As listing Of GXML . Doctor ; }
When you run the sample ReadFile method shown earlier, for each <Person> element in the file, the method either creates and saves a new tape or opens and updates an existing tape.
Additional Examples
This section contains some additional examples.
Flexible Reader Grade
The following case shows a more flexible reader method that accepts the filename, directory, class, and chemical element every bit input arguments. The method saves each object that it reads.
Class Readers . BasicReader Extends %RegisteredObject { ClassMethod Read ( mydir , myfile , grade , element ) { set reader = ##form ( %XML . Reader ) . %New ( ) if $extract ( mydir , $length ( mydir ) ) '= "/" { set mydir = mydir _ "/" } set file = mydir _ myfile set status = reader . OpenFile ( file ) if $$$ ISERR ( condition ) { do $System . Status . DisplayError ( condition ) } do reader . Correlate ( chemical element , class ) while reader . Next ( . object , . status ) { if $$$ ISERR ( status ) { do $System . Status . DisplayError ( status ) } gear up condition = object . %Salve ( ) if $$$ ISERR ( status ) { exercise $System . Status . DisplayError ( condition ) } } } }
Notice that when you read in a Person object, yous automatically read in its corresponding Accost object. (And when you lot save the Person object, you automatically save the corresponding Address object equally well.) This is a adequately crude technique that would be suitable but for bulk load of data; it does non brand whatsoever endeavour to compare to or update existing data.
In order to use this method, you would demand an XML-enabled class whose projection matched the incoming XML document. Suppose that you had XML-enabled classes named MyApp.PersonWithAddress and MyApp.Address. Also suppose that you had an XML document equally follows:
<? xml version = "1.0" encoding = "UTF-8" ?> < Root > < Person > < Proper noun > Able , Andrew </ Proper noun > < DOB > 1977-ten-06 </ DOB > < Address > < Street > 6218 Clinton Drive </ Street > < Metropolis > Reston </ Metropolis > < State > TN </ State > < Nix > 87639 </ Aught > </ Address > </ Person > </ Root >
To read the objects in this file and save them to deejay, you would practise something similar the following:
fix dir = "C:\XMLread-these" set file = "PersonData.txt" set cls = "MyApp.PersonWithAddress" set chemical element = "Person" practice ##class ( Readers . BasicReader ) . Read ( dir , file , cls , chemical element )
Reading a Cord
The post-obit method accepts an XML string, form, and element as input arguments. It saves each object that it reads.
Course Readers . BasicReader Extends %RegisteredObject { ClassMethod ReadString ( string , class , element ) { prepare reader = ##class ( %XML . Reader ) . %New ( ) set status = reader . OpenString ( cord ) if $$$ ISERR ( status ) { do $System . Condition . DisplayError ( status ) } do reader . Correlate ( chemical element , class ) while reader . Next ( . object , . status ) { if $$$ ISERR ( status ) { practice $System . Status . DisplayError ( condition ) } set status = object . %Save ( ) if $$$ ISERR ( status ) { practise $Arrangement . Status . DisplayError ( status ) } } } }
To use this method, you would practise something like the following:
ready cls = "MyApp.Person" set element = "Person" do ##class ( Readers . BasicReader ) . ReadString ( string , cls , element )
DocReleaseID: Core2018.1.7
Source: https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GXML_IMPORT
0 Response to "what would cause xmlreader to skip an element"
Postar um comentário