Showing posts with label XSLT. Show all posts
Showing posts with label XSLT. Show all posts

Sunday, 1 April 2018

Optimizing BizTalk Map Execution and Modularizing Map using Import XSLT


Here in this article, I would brief about optimizing map execution using XSL Compile Transformation and achieve Importing XSLT using helper component.

Let go straight into mapping scenarios, below is a use case where we have huge Inline XSLT code, this can be moved to separate xsl file as template and this file should be embedded as resource in BizTalk  assembly. As you see, we have moved the code to separate XSL file and within BizTalk using XSLT Scripting functiod, we would just call the actually template.
There can be a use case, where we have complete custom xsl instead of BizTalk mapper. Here, we have the main custom XSL which invokes the template in other XSL files. Refer below for the child template XSL files. Just to generalize, implementation here, I have created multiple child template XSL files and master template file which just imports these child templates and during runtime, we would import the master template in the BizTalk Map/Custom XSL file using Custom helper component.
Here is use case of multi-part message, we would use a similar approach to earlier one but challenge  is to merge/construct a multi-part message for our execution.
Overview of XSLCompiledTranformHelper, this would be used from orchestrations instead of Transform shape
Critical methods are shown below, if you observe GetMapInfo method, we dynamically import the master template xsl file and EmbeddedResourceResolver resolves imported xsl templates from the assembly.
Here are few critical helper classes.

Here is our orchestration uses XSLCompiledTransformHelper for transformation as shown below, which executes maps for different use cases mentioned in our problem statement.

Multiple part message can be executed either by combining messages into single message and executing the transform or by directly invoking the transform method with message params, as shown below.
I have referred below articles and added this feature to the XSL Compile Transformation component.
  • https://blogs.msdn.microsoft.com/paolos/2010/01/29/how-to-boost-message-transformations-using-the-xslcompiledtransform-class/
  • https://blogs.msdn.microsoft.com/paolos/2010/04/08/how-to-boost-message-transformations-using-the-xslcompiledtransform-class-extended/

Thursday, 7 July 2016

X-Path Queries on XML Document | BizTalk Server


Here, in this article I would brief about querying XML Document Node values using X-path 

XPath is used to navigate through elements and attributes in an XML document. It is a major element in W3C's XSLT standard. XPath uses path expressions to navigate in XML documents 
It contains a library of standard functions and is a major element in XSLT; without XPath knowledge you will not be able to create XSLT documents. 

XPath Terminology 

Nodes 

In xpath, there are seven kinds of nodes: element, attribute, text, namespace, processing-instruction, comment, and document nodes. 
XML documents are treated as trees of nodes. The topmost element of the tree is called the root element. 

x-path queries

Lets see about relationship between nodes and read element value using xpath with the below xml document, 

<OrderCollection> 
<AddressBookEntryIdentifier>1212121212</AddressBookEntryIdentifier>
  <ConsumerOrderNumber>100-200</ConsumerOrderNumber>
  <Orders>
    <Order>
      <MetadataCollection>
        <Metadata>
          <Name>LoanNumber</Name>
          <Value>100</Value>
        </Metadata>
        <Metadata>
          <Name>TID</Name>
          <Value>10</Value>
        </Metadata>
        <Metadata>
          <Name>ID</Name>
          <Value>11</Value>
        </Metadata>
        <Metadata>
          <Name>ProviderID</Name>
          <Value>1000</Value>
        </Metadata>
      </MetadataCollection>
      <OrderNumber>10000</OrderNumber>
      <ReferenceNumbers>
        <OrderReference>
          <ReferenceNumber>10101010</ReferenceNumber>
          <ReferenceType>FileId</ReferenceType>
        </OrderReference>
      </ReferenceNumbers>
    </Order>
    <Order>
      <MetadataCollection>
        <Metadata>
          <Name>LoanNumber</Name>
          <Value>200</Value>
        </Metadata>
        <Metadata>
          <Name>TID</Name>
          <Value>20</Value>
        </Metadata>
        <Metadata>
          <Name>EID</Name>
          <Value>21</Value>
        </Metadata>
        <Metadata>
          <Name>ProviderID</Name>
          <Value>2000</Value>
        </Metadata>
      </MetadataCollection>
      <OrderNumber>20000</OrderNumber>
      <ReferenceNumbers>
        <OrderReference>
          <ReferenceNumber>202020</ReferenceNumber>
          <ReferenceType>FileId</ReferenceType>
        </OrderReference>
      </ReferenceNumbers>
    </Order>
  </Orders>
</OrderCollection> 

Relationship of Nodes 

Parent 
  • Each element and attribute has one parent. 
    • In the sample shown; the Order element is the parent of the MetadataCollection, OrderNumber and ReferenceNumbers 
Child 
  • Element nodes may have zero, one or more children. 
    • In the example; the ReferenceNumber and ReferenceType elements are all children of the OrderReference element 
Siblings 
  • Nodes that have the same parent. 
    • In the sample shown example; the Name and Value elements are all siblings 
Ancestors 
  • A node's parent, parent's parent, etc. 
    • In the sample shown; the ancestors of the Order element are the Orders and OrderCollection elements 
Xpath Queries:

Select all the occurrence of an element irrespective of its parent, 
  • /*[local-name()='OrderCollection' and namespace-uri()='']/*[local-name()='Orders' and namespace-uri()='']/*[local-name()='Order' and namespace-uri()='']/*[local-name()='MetadataCollection' and namespace-uri()='']/*[local-name()='Metadata' and namespace-uri()=''] 
  • /*[local-name()='OrderCollection' and namespace-uri()='']/*[local-name()='Orders' and namespace-uri()='']/*[local-name()='Order' and namespace-uri()='']/*[local-name()='MetadataCollection' and namespace-uri()='']/*[local-name()='Metadata' and namespace-uri()='' and *[local-name()='Name' and namespace-uri()='' and .='ProviderID']]/*[local-name()='Value' and namespace-uri()=''] 
  • /*[local-name()='OrderCollection' and namespace-uri()='']/*[local-name()='Orders' and namespace-uri()='']/*[local-name()='Order' and namespace-uri()='']/*[local-name()='ReferenceNumbers' and namespace-uri()='']/*[local-name()='OrderReference' and namespace-uri()='' and *[local-name()='ReferenceType' and namespace-uri()='' and .='FileId']]/*[local-name()='ReferenceNumber' and namespace-uri()='']
Select an element within a specific parent 
  • /*[local-name()='OrderCollection' and namespace-uri()='']/*[local-name()='Orders' and namespace-uri()='']/*[local-name()='Order' and namespace-uri()='' and *[local-name()='OrderNumber' and namespace-uri()='' and .='10000']]/*[local-name()='MetadataCollection' and namespace-uri()='']/*[local-name()='Metadata' and namespace-uri()='' and *[local-name()='Name' and namespace-uri()='' and .='ProviderID']]/*[local-name()='Value' and namespace-uri()=''] 
Select parent with its child element 
  • //*[local-name()='Metadata' and namespace-uri()='' and *[local-name()='Name' and namespace-uri()=''and .='ProviderID']]
Select an element with its sibling 
  • //*[local-name()='Metadata' and namespace-uri()='' and *[local-name()='Name' and namespace-uri()='' and .='ProviderID']]/*[local-name()='Value' and namespace-uri()=''] 
Select an element with case insensitive evaluation using translate function 
  • /*[local-name()='OrderCollection' and namespace-uri()='']/*[local-name()='Orders' and namespace-uri()='']/*[local-name()='Order' and namespace-uri()='']/*[local-name()='MetadataCollection' and namespace-uri()='']/*[local-name()='Metadata' and namespace-uri()='' and *[local-name()='Name' and namespace-uri()='' and translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') ='id']] 
Select Ancestor/Parent with its child 
  • /*[local-name()='OrderCollection' and namespace-uri()='']/*[local-name()='Orders' and namespace-uri()='']/*[local-name()='Order' and namespace-uri()='' and *[local-name()='OrderNumber' and namespace-uri()='' and .='10000']] 
  • /*[local-name()='OrderCollection' and namespace-uri()='']/*[local-name()='Orders' and namespace-uri()='']/*[local-name()='Order' and namespace-uri()='' and *[local-name()='ReferenceNumbers' and namespace-uri()='' and *[local-name()='OrderReference' and namespace-uri()='' and *[local-name()='ReferenceNumber' and namespace-uri()='' and .='10101010']]]]
Conclusion
This article would help you understand writing xpath queries on xml and as BizTalk Server is a message-based system and all the messages that enter the BizTalk are converted to XML format, it would help you read elements inside maps/orchestration and pipeline components using xpaths