XML file: Use JScript, C #, and Visual Basic. Net to expand XSLT.

Source: Internet
Author: User
Tags types of extensions xsl xslt processor

XSL conversion (XSLT) is widely known for its ease of making difficult things easier and making easy things more difficult. It simplifies the Complex Conversion logic that is difficult to implement in other ways. At the same time, however, the function programming model of XSLT sometimes makes it extremely difficult to execute small business logic. Generally, traditional languages (such as VBScript, JScript, or Microsoft.. Net supports any language) The extended XSLT provides the best functionality in both aspects (for an introduction to XSLT, see the one I co-authored with Don box and John Lam in the August 2000 release.Article).

For example, consider the following XML document, which contains a series of operations to perform:

 
<Equation> <add> 3 </Add> <sub> 1 </sub> <Mul> 6 </MUL> <add> 8 </Add> <div> 4 </div> </equation>

Let's say that the goal is to evaluate the list of operations, top to bottom, assuming no operator precedence and an initial value of 0. in this case, it's like evaluating the following equation:

 
(3-1) * 6) + 8)/4) = 5

This problem can be solved in multiple ways. Depending on your background, the methods you used to solve the problem in the past, or even the common language, you may find that some solutions are intuitive, while others are rather obscure.

JScript Solution

You may have come up with how to use the imperativeProgramming Language(Such as Visual Basic, C ++, or JScript) and Dom to solve this problem. Using imperative languages that allow you to declare and update variables can greatly simplify tasks. The JScript function in Figure 1 extracts the node list that represents the sub-level of the equation element and calculates the result.

For many people, thisCodeThis is intuitive because JScript allows you to declare the result variables whose values can be updated in each loop iteration. This function can be called as follows:

 
VaR Doc = new activexobject ("msxml2.domdocument. 4.0 "); Doc. load ("numbers. XML "); var result = processequation (Doc. selectnodes ("/equation /*"));

XSLT Solution

Now, assume that you are using a language that allows you to declare variables, but when you assign values to them, these values cannot be modified. In other words, they are not actually variables, but constants specified at runtime. Function programming languages are a type of programming languages that share this feature. Scheme, ML, Haskell, XSLT, and other languages belong to this category.

Function languages are modular and flexible, so they are often used to solve extremely complex problems (AI is such an example ). In addition, function language implementation can be optimized in a way that is not currently available in mainstream imperative languages. However, all of these require a certain price, because the learning process is difficult for those who are not used to using function models.

For exampleProgramFor example, it uses anotherAlgorithmTo provide the same functions. The processequation template can generate the same result as the JScript function shown in Figure 1. This example is different from the JScript version because it does not use a for loop and does not update the variable after processing each operation. Instead, it uses recursion to process the list and uses the call stack to track incremental results after each operation.

XSLT + JScript Solution

If you can understand the code in figure 2 and feel as simple or simpler as the code in Figure 1, you may not need to read the rest of this column. However, like most developers, you will think that it is not the most intuitive programming model, especially for this simple task type. No one will oppose using XSLT to implement complicated XML Conversion logic, but these implementations may be too complex to their value when these transformations require some types of business logic.

In these cases, the combination of XSLT (for tree-based conversion logic) and another programming language (for a business logic) provides the best functionality in both aspects. The XSLT 1.0 specification integrates the Convention of using non-XSLT code to extend the XSLT program. These non-XSLT code can be written in any programming language supported by the given XSLT processor.

The XSLT program in Figure 3 shows how to add the JScript function in figure 1 to the XSLT program in Figure 2 to replace the processequation template. This method not only simplifies XSLT code, but also implements some functionality that cannot be implemented by other methods in many cases. For example, if you want to perform a mathematical operation that is not supported by the XSLT language itself, you must use a custom extension (I will introduce this example later ). If you use XSLT to perform complex transformations, you will usually encounter the need for custom extensions.

The disadvantage of this method is that the Extended features will only apply to processors that support the languages used. If your XSLT does not require portability between processors, you do not have to worry about this issue. If they require portability between processors, you must overcome the difficulties and determine how to use common XSLT code to implement this function. or, if this is not feasible, you must provide other implementation methods for each processor to be supported.

. Net and msxml xslt processors provide a simple mechanism to add code written in other languages, which can be directly implemented in the XSLT document, or by linking to an existing COM object or.. Net assembly. In the rest of this column, I will discuss details about how to extend the XSLT program with Microsoft implementations.

XSLT 1.0 Extension Mechanism

The XSLT 1.0 specification defines two types of extensions: extension elements and extension functions. These two types of extensions provide additional functions based on the standard language, and can be like any other XSLT 1.0 elements (including XSL: Transform, XSL: Template, XSL: value-of) or XPath 1.0/XSLT 1.0 functions (such as string, substring-before, sum, and document.

Because XSLT 1.0 has a template-based model, the XSLT processor needs to use additional information to correctly distinguish static content elements and extension elements that represent other additional behavior. For example, consider the following XSLT conversion:

<XSL: Transform version = "1.0" xmlns: XSL = "http://www.w3.org/1999/XSL/Transform" xmlns: Out = "http://www.w3.org/1999/xhtml" xmlns: ext = "http://example.org/extension"> <XSL: template match = "/"> <out: HTML> <Ext: dosomefunkymagic/> • </out: HTML> </XSL: Template> </XSL: Transform>

In this example, the processor identifies the elements (transform and template) associated with the http://www.w3.org/1999/XSL/Transform namespace as language-specific instructions and treats other elements (HTML and dosomefunkymagic) identifies the content that should be output when the template is instantiated.

Now let's assume that the dosomefunkymagic element is specified as an extension element by a certain type of processor. To enable the processor to find this element, it needs to know which namespace contains the extension element being used. This can be done by using the extension-element-prefixes attribute on the stylesheet/transform element, as shown below:

<XSL: Transform version = "1.0" xmlns: XSL = "http://www.w3.org/1999/XSL/Transform" xmlns: Out = "http://www.w3.org/1999/xhtml" xmlns: EXT = "http://example.org/extension" extension-element-prefixes = "Ext"> <XSL: template match = "/"> <out: HTML> <Ext: dosomefunkymagic/> </out: HTML> </XSL: Template> </XSL: Transform>

Now, when the processor executes the conversion, it can determine that dosomefunkymagic represents the extension element, not just the general output.

This is not a problem with extended functions, because, as I explained earlier, they will not be confused with the output content. This means that if you only use an extension function, you do not need to use the extension-element-prefixes element, but you still need to use an extension namespace to limit the function name:

 
<XSL: Transform version = "1.0" xmlns: XSL = "http://www.w3.org/1999/XSL/Transform" xmlns: Out = "http://www.w3.org/1999/xhtml" xmlns: ext = "http://example.org/extension"> <XSL: template match = "/"> <out: HTML> <XSL: value-of select = "Ext: dosomefunkymagic ()"/> </out: HTML> </XSL: template> </XSL: Transform>

All built-in XPath 1.0 and XSLT 1.0 function names are not limited, which means they are always serialized as ncname and are assumed not to come from any namespaces. Therefore, if the processor encounters a function name with a prefix, it is automatically assumed to be an extension function.

The XSLT 1.0 specification also provides a mechanism that allows conversion to processor query extension support. In particular, it defines functions available for element and function, so that you can determine whether it supports expansion before trying to use the execution processor. Using these functions with if or choose elements, you can write XSLT transformations that utilize some extensions without completely sacrificing portability, as shown in figure 4.

XSLT 1.0 also provides a fallback element and uses it as a more explicit replacement method for providing backup functionality. After you place the backup feature inside the fallback element, you can use it within any extension element that may not be supported. Figure 5 shows the previous example of porting to use the fallback element.

While specifications provide support for CPU-specific extensions, there is no standard mechanism to implement them. This mechanism varies by processor, but most modern implementations currently provide this support (a standard approach may be provided in future XSLT specifications ). Let's take a look at how this mechanism works in Microsoft MSXML 4.0 and. Net XSLT implementations.

Msxsl: script

The current Microsoft XSLT processor can be expanded directly in the XSLT document or within the out-of-band extension object. This section describes some examples of the first method. As explained in the example, you can use the script element of the Microsoft urn: Schemas-Microsoft-com: XSLT namespace (from now on, I will call it the msxsl: script element ), embed the extension code into the XSLT document. Msxsl: the script element itself is an extension element, so you can test whether it is supported as discussed in the previous section.

The syntax that you must use for msxsl: script is listed below in MSXML 4.0 and. Net:

<Msxsl: scriptlanguage = "language-name" implements-Prefix = "prefix of user's namespace"> </msxsl: SCRIPT>

The language attribute specifies the language used in the script tag, while the implements-Prefix attribute controls the namespace in which the function is located. You must use a qualified name to call one of these user-defined functions in an XPATH expression.

In MSXML and. Net implementations, the languages that can be used are different. In MSXML (starting from version 2.0), you can use VBscript or JavaScript. However, in. net, you can use any language supported by. net, including C #, Visual Basic, JScript. net, and even JScript. Use the capabilities of strong-type languages (such as C # and Visual Basic. net) to make them more attractive.

Go back to Figure 3. This figure shows the combination of msxsl: script and JScript. Note that processequation is associated with the urn: The-XML-Files: XSLT namespace, urn: The-XML-files: bind the XSLT namespace to the USR prefix in The namespace Declaration of the transform element. Whenever a function is used, its name must contain the USR prefix. In that example, the function is called in the value-of select expression, as shown below:

 
<XSL: value-of select = "USR: processequation (/equation/*)"/>

Because both Microsoft XSLT implementations support JScript, the document shown in Figure 3 can be used for MSXML or. NET versions.

Using these two Microsoft implementations, you can write extension functions in different languages by using multiple msxsl: script elements in a single XSLT document (for example, see Figure 6 ). The only problem with this operation is that each msxsl: script element must specify a different namespace in the implements-Prefix attribute. You cannot write extension code for the same namespace in multiple msxsl: script elements. The remaining details about msxsl: script are different in these two implementations.

Ing type between XSLT and MSXML

The code in Figure 6 shows information transmitted in two directions. The object is passed to the function as a parameter and returned from each function as a return value. You must understand how the XPath type system maps to the JScript and VBScript type systems to correctly design your own extension functions.

The table in Figure 7 describes the types mapped to JScript and VBScript when each XPath type is used for function parameters. The first three types are very direct. Strings, numbers, and boolean values in XPath are directly mapped to strings, numbers, and boolean values in JScript and vbscriptin. As an example, the function used in Figure 6 returns the strings in the JScript and VBScript functions to the XSLT value-of call expression.

The last two types will require more explanation. The XPath node Assembly maps to the JScript and VBScript objects that implement the DOM nodelist interface (ixmldomnodelist. Ixmldomnodelist is essentially a collection interface of common DOM nodes. It supports basic traversal and length query.

Let's take a look at an example of how to use ixmldomnodelist in an extension function. Assume that you need to calculate the distance between two points in the following XML document:

<Line> <point> <x> 10 </x> <Y> 10 </Y> </point> <x> 20 </x> <Y> 20 </Y> </point> </line>

This cannot be achieved through standard XSLT, but with the help of extended functions and more advanced mathematical libraries, this task will become easier. The extended function shown in Figure 8 gets an ixmldomnodelist object that represents a set of two points. It can use the built-in JScript math object to calculate the distance between two points:

Then, you can call this extension function as follows:

 
Distance: <XSL: value-ofselect = "Math: calcdistance (/line/Point)"/>

The XSLT result tree snippets are also mapped to ixmldomnodelist objects, but they only contain nodes of the node_document_fragment type. In other words, you must locate the child level of the ixmldomdocumentfragment object to perform actual processing. The XSLT in Figure 9 illustrates how to process the result tree Fragment passed to the function.

Extended functions of this version will receive a result tree segment. Result tree fragments are generated using XSLT variables or Param elements. The following XSLT snippet illustrates how to generate a result tree snippet and call this new version of extended functions:

• <XSL: variable name = "points"> <point> <x> 10 </x> <Y> 10 </Y> </point> <x> 20 </x> <Y> 20 </Y> </point> </XSL: variable> <XSL: value-of select = "Math: calcdistance ($ points)"/> •••

The types listed in figure 7 are unique types available in function parameters. Since JScript and VBScript are not strongly typed, you must be clear about the object type passed during function call. Consider the following extended functions:

 
<XSL: value-ofselect = "USR: dosomething (string (./author/name), number (./price),.)"/>

If the function gets parameters of the string, number, and ixmldomnodelist types respectively, you must explicitly force them when calling methods, as shown below:

 
<XSL: value-ofselect = "USR: dosomething (string (./author/name), number (./price),.)"/>

In this example, the string and number functions of XPath are used to explicitly force the first two node sets to the expected type. The last parameter does not need to be forced because the node assembly is automatically mapped to the ixmldomnodelist object.

There are more restrictions on function return values in MSXML. The types returned by the function can only be strings and numbers (see figure 10 ). If a number is returned, it is forcibly set to JScript and VBScript number. If other primitive types are returned, it is forced to be JScript/VBScript string. An exception is thrown when an attempt is made to return an object.

For example, the following extended functions return numbers, which are acceptable.

 
<MS: script language = "VBScript" implements-Prefix = "VB"> <! [CDATA [function authorsbystate (state) set Doc = Createobject ("msxml2.domdocument. 4.0 ") Doc. load "authors. XML "// returns the number of authors for given stateauthorsbystate = Doc. selectnodes ("// Author "). lengthend function]> </MS: SCRIPT>

However, the following slightly modified version attempts to return an ixmldomnodelist object to the caller, causing an exception:

 
<MS: script language = "VBScript" implements-Prefix = "VB"> <! [CDATA [function authorsbystate (state) set Doc = Createobject ("msxml2.domdocument. 4.0 ") Doc. load "authors. XML "// returns the authors collectionfindauthorsbystate = Doc. selectnodes ("// Author") end function]> </MS: SCRIPT>

You can instantiate and call objects within an extension function, but you cannot return them to the caller.

Ing type between XSLT and. net

The mechanism for constructing. Net extension functions is similar to the MSXML mechanism I just discussed. However, the. NET implementation is more advanced than MSXML for the following reasons. First, you can select more languages, including strong languages such as C # and Visual Basic. net. Secondly, the extension function can be a strong type function, which allows the processor to handle certain forces for you in the function call era. Finally, the object (except string and number) can be used as the return value.

Figure 11 illustrates the XPath ing between XPath and. NET systems. This ing applies to two directions: function parameters and return values. The first three types are mapped. net System. string, system. boolean and system. double type, and the node set and result tree fragments are mapped to xpathnavigator and xpathnodeiterator respectively. (For more information about these classes, see the XML files column in September 2001. Int16, uint16, int32, uint32, int64, uint64, single, and decimal types are automatically forced to be double, thus ing to W3C XPath number type. If any other type is used in function parameters or return values, an exception is thrown. These type mappings can also be applied to XSLT global parameters.

Consider the following versions of the calcdistance Extension function, which is implemented in C:

<MS: script language = "C #" implements-Prefix = "math"> <! [CDATA [double calcdistance (xpathnodeiterator points) {points. movenext (); double xdelta = (double) points. current. evaluate ("X-following: X"); double ydelta = (double) points. current. evaluate ("Y-following: Y"); Return math. SQRT (math. pow (xdelta, 2) + math. pow (ydelta, 2) ;}]> </MS: SCRIPT>

Note that this function accepts the xpathnodeiterator parameter and returns a double-precision value. This function can be called like the previous function implemented in JScript:

 
<XSL: value-of select = "Math: calcdistance (/line/Point)"/>

This example also uses the system. Math class. However, please note that the Code does not contain any C # statements used #.. Net will make the namespace listed in figure 12 automatically available in the msxsl: script extension. Currently, you can only use the namespace type in the msxsl: script extension. If you need to use other types, you must rely on XSLT extension objects (I will discuss them later ).

Reusability

It is convenient to directly embed the extension code in the XSLT document. However, improper design may limit reusability. To reuse the custom functions defined in msxsl: script, you can use the include element of XSLT. You can create a global library that only contains extension functions in the XSLT document. For example, the XSLT document in Figure 13 contains only one msxsl: script element, which contains several functions.

Assuming that this file is named global-extensions.xsl, the following example shows how to include this file in another XSLT document:

 
<XSL: Transform version = "1.0" xmlns: XSL = "http://www.w3.org/1999/XSL/Transform"> <XSL: Include href = "global-extensions.xsl"/> • </XSL: Transform>

This is similar to the use of ASP include elements to reuse scripts embedded in ASP pages. Although this method is feasible, the preferred method for reusability is the XSLT extension object.

XSLT extension object

Both MSXML and. Net Support XSLT extension functions in compiled components. You can use MSXML to call the compiled COM component, and use. Net to call the compiled assembly. The specific details depend on the implementation method you want to use.

In MSXML implementation, the COM Extension object supports setting and querying attributes and calling functions. Like msxsl: script extensions, the types used in functions and attributes must follow the ing rules described in Figure 7 and figure 10.

To use an extension object in the XSLT document, you need to add it to the context of the processor before executing the conversion. You can achieve this through the addobject method exposed by the imo-processor interface in MSXML. The syntax is as follows:

 
Objdomainprocessor. addobject (OBJ, namespaceuri );

Addobject will get a namespace identifier associated with the object. This is equivalent to using the implements-Prefix attribute of the msxsl: script element. After an object is added to the context of the processor and associated with the provided namespace, it can be called from the XPath expression (as shown in 13 ).

In XSLT, you should add get-or put-followed by parentheses before the property name to access the property. For example:

 
Get-age (), put-age (33 ))

Let's look at a complete example of defining and using extended objects. Let's assume the following Visual Basic class definition:

 
'Class: personpublic name as stringpublic age as doublepublic function sayhello (byval other as string) as stringsayhello = "hello" & Other & ", I'm" & nameend Function

To use a person object as an XSLT extension, you must add it to the context of the processor before executing the conversion. Figure 14 illustrates how to use MSXML 4.0 and Visual Basic to perform this operation. Because the object referenced by P has been added to the context of the processor before transform is called, as long as the property name and function name of person are limited by the urn: person namespace, the XSLT document can access the attributes and functions of person, as shown below:

<XSL: Transform version = "1.0" xmlns: XSL = "http://www.w3.org/1999/XSL/Transform" xmlns: OBJ = "urn: Person"> <XSL: output method = "text"/> <XSL: template match = "/"> name: <XSL: value-of select = "OBJ: Get-Name ()"/> Age: <XSL: value-of select = "OBJ: Get-age ()"/> greeting: <XSL: value-of select = "OBJ: sayhello ('michi ') "/> </XSL: Template> </XSL: Transform>

The models in. Net implementation are almost the same, except for calling. Net objects. The main difference is how to associate an object with the context of the processor. You can use the xsltargumentlist class as follows:

 
Transform transform XSLT = new transform (); XSLT. load (stylesheet); xpathdocument Doc = new xpathdocument (filename); inclutargumentlist incluarg = new inclutargumentlist (); // Add a person objectperson OBJ = new person (); obj. name = "Michi"; obj. age = 6; running Arg. addextensionobject ("urn: person", OBJ); XSLT. transform (Doc, xslarg, console. out );

The XSLT document used to call the. NET extension object looks the same as the document in the previous MSXML example.

Summary

XSLT is a powerful function programming language. It can make difficult tasks easier and make easy tasks more difficult. In some cases, function programming models using XSLT are combined with imperative languages (such as JScript, C #, or visual basic.. net) to simplify the entire XSLT document. Microsoft's XSLT implementations in MSXML and. Net provide excellent support for creating this type of hybrid XSLT Application.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.