Each application processes data differently when it receives a response from Tamino as a result of a query. The Tamino API for .NET provides several methods and classes for accessing query results appropriately, satisfying various requirements for further processing.
For further processing, it may be convenient to access the results of a
query as a Stream
; alternatively, it may be more
convenient to access them as an XmlReader
. These options
are supported by the methods QueryStream
and
QueryReader
of the
TaminoCommand
class, respectively.
The QueryXmlReader sample in the QuerySamples demonstrates using the
QueryReader
method to apply an XSL transformation to
the query result.
... XmlReader reader = command.QueryReader(query); XPathDocument xpathDoc = new XPathDocument(reader); XslTransform xslTransform = new XslTransform(); xslTransform.Load("mystylesheet.xsl"); xslTransform.Transform(xpathDoc, null); ...
A query may return just one simple value as its result. The
GetSingleItem
method in the
TaminoQueryResponse
enables you to access a simple
result simply. See also the IntegerQuery example in the QuerySamples.
TaminoQuery query = new TaminoQuery("count(input()/Property") TaminoQueryResponse qr = command.Query(query); int result = (int) qr.GetSingleItem(typeof(int));
You can also specify a complex type as the parameter to the
GetSingleItem
method. Any type that can be serialized
and deserialized by .NET's XmlSerializer
class is
supported.
The Tamino API for .NET provides two classes
for iterating over query result sets: TaminoPageIterator
and TaminoItemIterator
. Your application can use the
convenient foreach
statement to iterate over the
query results.
Both classes can be used to process query results, whether a Tamino cursor has been used for the query or not. Tamino cursor usage is completely hidden from the application. However, if a cursor was not used for the query, all the query result items are returned in one page and therefore there is only one page to iterate over.
The TaminoItemIterator
can be used to iterate
over the complete query result. Item iteration crosses page boundaries
seamlessly.
... TaminoQueryResponse qr = command.Query(query, 10); // pagesize=10 foreach (XmlNode node in qr) { Console.WriteLine(node.OuterXml); } qr.Close(); ...
The TaminoItemIterator
can also be used in
conjunction with a TaminoPageIterator
, so that the
application can navigate pagewise through the query result, and then request a
TaminoItemIterator
to iterate over the results within a
single page.
... TaminoQueryResponse qr = command.Query(query, 10); // pagesize=10 TaminoPageIterator pageIt = qr.GetPageIterator(); foreach (XmlDocument page in pageIt) { TaminoItemIterator itemIt = pageIt.GetItemIterator(); foreach (XmlNode node in itemIt) { Console.WriteLine(node.OuterXml); } } qr.Close(); ...
An application can iterate forwards and backwards over the query results.
... TaminoQueryResponse qr = command.Query(query, 10); // pagesize=10 TaminoPageIterator pageIt = qr.GetPageIterator(); while(pageIt.Next()) { XmlDocument page = pageIt.GetPage(); ... } while (pageIt.Previous()) { XmlDocument page = pageIt.GetPage(); ... } qr.Close(); ...
Note:
After modifying items in a page and writing the modifications back
to the database, you will see the old values when you iterate over this page
again.
See also the QueryPageIterator, QueryItemIterator and QueryNoTaminoCursor examples in the QuerySamples.
If the query result set is a list of complete root elements of Tamino
XML documents, the application can use the serialization class
TaminoXmlDocument
to access the individual result items
within this list, make modifications, and write the modified items back to the
Tamino database.
TaminoQuery query = TaminoXmlDocument.BuildQuery(null, "input()/Property[@Category=’Buy’]"); TaminoQueryResponse qr = command.Query(query, 10); // pagesize=10 TaminoItemIterator itemIt = qr.GetItemIterator(); while(itemIt.Next()) { TaminoXmlDocument doc = (TaminoXmlDocument) itemIt.GetItem(typeof(TaminoXmlDocument)) XmlElement elem = (XmlElement) doc.Data; // ...make some changes to elem TaminoResponse response = command.Update(doc); ... }
You can find the complete sample code in the ProcessingDocumentList sample of the QuerySamples.
Similarly, you can use the class
TaminoXmlDocumentProperties
to get a list of document
properties which you can subsequently use to access the documents themselves.
For more information, see the Tamino API for .NET
Reference Documentation.
That’s all you need to know in order to use document lists successfully in your own applications. If you want to know more about this technique, the following paragraphs describes how it works internally.
TaminoXmlDocument.BuildQuery
modifies the
specified query expression so that the query result will look like this:
<?xml version="1.0" encoding="iso-8859-1" ?> <ino:response ...> <xq:query> <![CDATA[ namespace tf='http://namespaces.softwareag.com/tamino/TaminoFunction' for $p in input()/Property[@Category='Buy'] return <TaminoDocument doctype={tf:getDoctype($p)} docid={tf:getInoId($p)}>{$p}</TaminoDocument> ]]> </xq:query> ... <xq:result xmlns:xq="http://namespaces.softwareag.com/tamino/XQuery/result" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tf="http://namespaces.softwareag.com/tamino/TaminoFunction"> <tan:TaminoDocument tan:docid="1" tan:doctype="Property" xmlns:tan="http://namespaces.softwareag.com/tamino/TaminoAPI4DotNet"> <Property Category="Buy" PropertyType="2-Room-Apartment"> ... </Property> </tan:TaminoDocument> <tan:TaminoDocument tan:docid="2" tan:doctype="Property" xmlns:tan="http://namespaces.softwareag.com/tamino/TaminoAPI4DotNet"> <Property Category="Buy" PropertyType="4-Room-Apartment" > ... </Property> </tan:TaminoDocument> </xq:result> </ino:response>
TaminoXmlDocument
can be serialized and
deserialized using .NET's XmlSerializer
class. After
deserializing the first result item by calling
iterator.GetItem(typeof(TaminoXmlDocument))
, the public fields and
property of the TaminoXmlDocument
object contain the
following values:
DocName | "@1" |
DocType | "Property" |
ContentType | "text/xml" |
IsXml | True |
Date |
<Property Category="Buy" PropertyType="2-Room-Apartment"> ... </Property> |
TaminoXmlDocument
implements the
ITaminoDocument
interface. This allows it to be passed
on to the Update
method of the
TaminoCommand
class.
An application can always update any node of a Tamino XML document by
performing XQuery updates via the Query
method of the
TaminoCommand
class in a descriptive way (see
Performing Queries and Update
Queries). However, if the query result set comprises a list
containing uniform subtrees of a Tamino XML document, it may be better if the
application uses a more object-oriented technique to access the individual
result items, make modifications, and write the changes back to the Tamino
database. The ProcessingNodeList example in the QuerySamples demonstrates using
a simple class like MyXmlNode
to process node lists more
conveniently.
... string expr = "input()/Property/ContactPerson"; MyXmlNode.Selector = ".//ContactPerson"; MyXmlNode.Field = "Name"; TaminoQuery query = MyXmlNode.BuildQuery(expr); TaminoQueryResponse queryResponse = command.Query(query, 10); // pagesize=10 TaminoItemIterator itemIt = queryResponse.GetItemIterator(); while (itemIt.Next()) { MyXmlNode item = (MyXmlNode) itemIt.GetItem(typeof(MyXmlNode)); XmlNode contact = item.Data; // make some modifications TaminoQuery updateQuery = item.BuildUpdate(); TaminoQueryResponse updateResponse = command.Query(updateQuery); ... } ...
To update an individual query result item, the item must be uniquely
identified in the Tamino database. In this example, the
MyXmlNode
class uses a similar concept to the
<unique>
constraints as it is defined in XML Schema: the application
specifies sub-tree uniqueness within the scope of the XML document that
contains the sub-tree. This is done by setting MyXmlNode.Selector and
MyXmlNode.Field accordingly. The MyXmlNode
class uses
the same mechanism as the TaminoXmlDocument
class to
identify the XML document.
The following steps are performed when modifying the phone number for a
ContactPerson
item:
MyXmlNode.Selector = ".//ContactPerson"
and
MyXmlNode.Field="Name"
specify how a single
ContactPerson
element can be uniquely identified within
a Property document: each ContactPerson
element is
identified uniquely by its "Name" child. Notice that
the scope of uniqueness is just a single document. The
"Name" value does not have to be unique over all
Property documents.
MyXmlNode.BuildQuery(expr)
modifies the specified query
expression so that the query result will contain identifying information for
the XML documents affected by this query.
A single item in the query result set might look like this:
<MyXmlNode doctype='Property' inoid='10'> <ContactPerson> <Name>Glenn Carter</Name> <Phone>1-361-842-3875</Phone> <Email>Glenn.Carter@automailer.com</Email> </ContactPerson> </MyXmlNode>
When iterator.GetItem(typeof(MyXmlNode))
is executed for
the item in step 2 above, the properties and fields of the
MyXmlNode
instance will contain the following
values:
TaminoInoId | "10" |
DocType | "Property" |
Data |
<ContactPerson> <Name>Glenn Carter</Name> <Phone>1-361-842-3875</Phone> <Email>Glenn.Carter@automailer.com</Email> </ContactPerson> |
m_oldfield | "Glenn Carter" |
Assume that the application changes the
Data
property so that it contains the new phone
number:
<ContactPerson> <Name>Glenn Carter</Name> <Phone>9-999-999-9999</Phone> <Email> Glenn.Carter@automailer.com </Email> </ContactPerson>
item.BuildUpdate()
uses the MyXmlNode.Selector and
MyXmlNode.Field settings and the m_oldfield and Data values to create the
following update query:
namespace
tf='http://namespaces.softwareag.com/tamino/TaminoFunction' update replace for
$p in input()/Property//ContactPerson where tf:getInoId($p)=10 and
$p/Name="Glenn Carter" return $p with <ContactPerson><Name>Glenn
Carter</Name><Phone>9-999-999-9999</Phone><Email>Glenn.Carter@automailer.com</Email></ContactPerson>
TaminoQueryResponse
,
TaminoItemIterator
and
TaminoPageIterator
implement .NET's
IEnumerable
and IEnumerator
interfaces. This allows an application to bind query results directly to .NET
Web controls.
The following example queries all names of contact persons from Tamino and shows them in a list box. You can find the Property schema and corresponding example data in the samples.
... protected System.Web.UI.WebControls.ListBox ListBox1; ... TaminoQuery query = new TaminoQuery("input()/Property/ContactPerson/Name")); TaminoQueryResponse qr = command.Query(query); ListBox1.DataSource = qr; ListBox1.DataTextField = "InnerText"; ListBox1.DataBind(); ...