Avectra.netForum.xWeb.DynamicXmlBuilder

Overview

netFORUM contains a class that allows you to build and deploy metadata-driven Xml Web Services in minutes. The DynamicXmlBuilder will drive a web method that returns any data in an Xml node to a calling program. Calling programs are authorized by logging their IP to prevent unauthorized calls to your data.

For example, suppose you need a web service that an outside vendor can call that will retrieve data about netFORUM Events. The vendor’s development tools can use Web Services. Ideally, you would like to create a web service that the vendor can call and have it return data in an Xml node.

netFORUM’s dynamic XmlBuilder can help you build this.

First, think about what data you want to return. It may be helpful to write simple queries in a SQL Query Analyzer to determine this. Later, you will configure netFORUM to run these same queries through a web service.

The DynamicXmlBuilder's metadata setup can also be used by the XslGenerator to define XML datasets from netFORUM data that can be transformed through XSL and displayed on a CMS web page.

Configuring a DynamicXmlBuilder

The DynamicXmlBuilder is configured in the Toolkit module of netFORUM from the XML Web Service group item.

There are three main elements of a DynamicXmlBuilder:

  1. Web Service
  2. Web Service Method (child of Web Service)
  3. Web Service Method Node (child of Web Method). There is always one root node, and then there can be any number of child nodes in a tree formation. This concept is very much like a child form and then nested grand-child and great-grand-child forms.

Once you have the metadata setup, then you can reference this definition in either a .NET web service that you create, or from theXslGenerator using the {BeginXmlBuilderService}{EndXmlBuilderService} and {BeginXmlBuilderMethod} {EndXmlBuilderMethod} } metatags.

Web Service

Go to netFORUM’s Toolkit content group and navigate to the XML Web Service content item. Add a new web service definition, giving it the name and namespace of the web service you have just created or the one you want to call through the XslGenerator. It really does not matter how you name these; just name then in a way that will make sense to you.


Web Service Method

Next, from the web method child form, add the web method from the web methods child form, making sure you name the web method the same as you named the web method in the ASMX or from the XslGenerator:


If your web service has multiple methods, you may add them all here as shown in this example from a different site:


Once the web method has been added, click the goto to navigate to the new web method.

For organizational purposes, you might want to group web methods under web services based on a functional area, based on vendors who will use the methods, or any other appropriate logic.

Web Service Method Node

Next you will add one root node to the web method. In this example the root node is called GetEventSummary.


Next expand the folder on the root node, add a sub-node to this node:


In this example the sub-node is called EventDetail. In our sub-node we will enter the SQL from our Query Analyzer, adding in the parameters as well. You could add sub-sub-nodes, for example, to show sessions under the event. Here is the example:

Every column in the resulting recordset will be output in the XML (with some exceptions, see below). The SQL Statement (or stored procedure) must return only one table or recordset. If the SQL returns two tables/recordsets, then only the first table will be output in XML. If you feel like your SQL needs to return two or more tables to accomplish your need, then you should break these out into separate nodes at the same level, or as parent and sub-nodes. Example, if your SQL has this:

SELECT a, b, c FROM sometable WHERE x=1
SELECT q, r, s FROM othertable WHERE y > 9

With this node SQL, only a, b and c will be output in the XML. The second table (with q, r, s) will be ignored.


Parameters

Parameters will be passed into the SQL in your nodes from the web method’s DynamicXmlBuilder, or from the XslGenerator's metatags {BeginXmlBuilderParams}{EndXmlBuilderParams}. Once these parameters are passed by the DynamicXmlBuilder into your node sql, then the values can be parsed by your SQL as shown above for {EventType}, {DateFrom} and {DateThru}. Incoming parameters are not parsed in the root node, but can be parsed in the first node or nodes within the root node.

If you want to send incoming parameters into a deeper node, then you will need to send them into the first node and then pass them along from there.

Underscore Character in Column Alias

Note also the [_evt_key] parameter; the DynamicXmlBuilder will not output any elements that begin with an underscore character, but those columns will be available for evaluating in subnodes. The eventdetail node has a sub-node for sessions, and this subnode filters the sessions based on the [_evt_key].

CDATA Elements

Finally, note the CDATA element. The DynamicXmlBuilder will output this as a CDATA element with better support for HTML characters; the actual characters CDATA_ will also be removed from the element name, so when the Xml is rendered the element above will be named <EventDescription/> instead of <CDATA_EventDescription/>.

Web Service Method Security

If you are developing the DynamicXmlBuilder for a web service, you can implement security by setting up a list of authozied IPs. For XslGenerator, disregard this section. If working with the ExecuteMethod web method in xWeb, see that article as security works differently.

After adding your second node as shown above, add an authorized web server, entering your own work station as an IP. Eventually you will need to add the IPs of any webservers who will also need to access this method.

Using Hierarchical Container Nodes

If some cases you might want an Xml document to have a “container” for sub-nodes such as the following:


Notice that we have a <Prices/> sub-node with multiple <Price/> sub-sub-nodes within it. The <Prices/> sub-node contains no attributes or elements (although it could), it simply “contains” zero, one or more <Price/> node(s).

Here is the structure of the nodes:


The <Prices/> sub-node contains node sql that will return no output, but will return a SQL recordset result internally that can, in turn, be parsed in its own <Price/> subnode. The only XML that is output is the element name. There are no elements output because the column alias begins with the underscore character, which directs the DynamicXmlBuilder to suppress its output as an element.

Here is the <Prices/> node and its node sql. You will see that the node sql is simply “handing down” the {_prd_key} from the <ProductListing/> as it traverses downward to the <Price/> node by way of this intermediate <Prices/> “container” node.


We are assuming that {_prd_key} is a column alias in the parent <ProductListing/> node that is above the <Prices/> node.

Next, the <Price/> node (which is the sub-node of its parent <Prices/>) returns any prices for its <Product/> by using the {_prd_key} that is returned by the parent <Prices/> node:


If you were to omit the <Prices/> “container” sub-node, then you would simply output the <Prices/> directly under the <ProductListing/> node. The XML would look like this:


The Nodes setup would be like this instead:


The <Prices/> node would be like this instead:


There is no right or wrong way to do this. Both are valid XML. It depends on the requirements and the preferences of the developer who will be integrating with the web service.

Node Stops Traversing

Suppose you have a nested, nested nodes. If no record is returned in a node, then it will stop traversing downward; the program thinks it is "done" with that branch, and it will keep looping. If you want the XmlBuilder to keep traversing, even if no records are returned, then you will need to do the following trick: give the node a meaningless Node Attribute which will cause the XmlBuilder to keep traversing downward through that branch.

Form example, where the node is called NameOfNode:

SELECT [NameOfNode~nodeattribute~version] = '1.0'

Unfortunately, this will require a SQL statement to run each time this node is processed.

Node and Element Attributes and Text Values

The examples we see on this page contain conventional xml nodes and text elements. If you want a node or an element to have attributes such as we see below in the <XELIG version="1.00"> node and the <exam programid="Annual" examid="ABC Level 3 Exam" /> element of the event subnode, then read the main article. This article also looks as setting the value of node.


Using the ~nosql~ Directive

Advanced topic for speeding up certain DynamicXmlBuilder case studies.

Cache DynamicXmlBuilder XML Results

The DynamicXmlBuilder allows for caching an Xml response in a file saved on the web server. For busy web services, this can provide a dramatic benefit in speed and a reduction in network traffic and SQL Server activity. These benefits are balanced, of course, by the loss of real time data.

Generally not appropriate for XslGenerator but could be useful for developing .NET web services.


Summary of DynamicXmlBuilder Special Characters

If the column alias returned by the record set in the node sql contains any of these special characters, then the following will occur:

Character Action
First character of column alias is an underscore Column in recordset will not be output in Xml but will be available internally for subnodes
~attribute~ Outputs as element attribute instead of element value
~nodeattribute~ Sets a node attribute and value for the Xml Node
~nodetext~ Sets the text value of a node element
~nosql~ Skips unnecessary database calls, when possible. See ~nosql~ section

XslGenerator Case Study

Referring to the examples above, an XslGenerator definition for a DynamicXmlBuilder could be the following:

{BeginXmlBuilderService}netFORUMAUDC2005.netForumDynamicXmlBuilderWebService{EndXmlBuilderService}
{BeginXmlBuilderMethod}GetEventSummary{EndXmlBuilderMethod}
{BeginXmlBuilderParams}eventType={evt_code};DateFrom={date_from};DateThru={date_thru}{EndXmlBuilderParams}

{BeginXslFileName}<<..enter file name here..>>{EndXslFileName}

The definition above assumes that somehow an incoming parameter will come for {evt_code} as well as {date_from} and {date_thru}.

The XslFile will then transform the XML pulled in from the <EventDetail> node and any of its subnodes.

Quick Checklist for XslGenerator:

  1. In Toolkit module, add the Web Service
  2. Add a Web Method to the web service.
  3. Add a root node with an empty node sql.
  4. Add a sub-node to the root node, give it a name, enter the SQL in the node sql and be sure to include the incoming parameter(s) as parsed values in the WHERE clause of the SQL. You may also use a Stored Procedure.
  5. In the content information of the content detail, reference your DynamicXmlBuilder metadata you just set up as shown in the beginning of this section, as shown a couple of paragraphs above.

XslGenerator Best Practices

If you have multiple web content details that all need to use the same XML Data Source structure, but have varying parameters, it can be advantageous to set this up as a DynamicXmlBuilder instead of entering the SQL/XML definition in every content detail using {BeginXmlBuilderXml} metatags. By using the XmlBuilder definition in metedata as shown on this page, you need to set this up in only one place, and if you ever need to refine the definition, you only need to do it in one place.

Implementing DynamicXmlBuilder in Web Service Code

A DynamicXmlBuilder is a public class that can be used in Visual Studio .NET to construct XML documents. For example, you can develop a web service that returns an XmlNode. The XmlNode can be constructed with a DynamicXmlBuilder metadata definition. This is a powerful way to develop metadata-driven web services without writing a lot of code.

Publish RSS Feeds

The DynamicXmlBuilder can be used to publish RSS feeds generated based on data in your netFORUM site. The item links in the RSS feed can, in turn, point to CMS web pages in your eWeb site. Web Posting most commonly will drive the content.