Showing posts with label xpath. Show all posts
Showing posts with label xpath. Show all posts

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

Business Rule Engine (BRE) | BizTalk | Part-1


The Business Rules Framework is a Microsoft .NET-compliant class library. It provides an efficient inference engine that can link highly readable, declarative, semantically rich rules to any business objects (.NET components), XML documents, or database tables. 

Application developers can build business rules by constructing rules from small building blocks of business logic (small rule sets) that operate on information (facts) contained in .NET objects, database tables, and XML documents. This design pattern promotes code reuse, design simplicity, and modularity of business logic. 

BRE uses Rete algorithm; a highly efficient algorithm for implementing business rule engines. BRE can be invoked from Orchestration Process or from a C# method; here, I would cover those as well. 

Overview of BRE
  • Business Rule Composer: GUI, this helps us to create, manage, and test policies. 
  • Policy: In a Policy, we can define rules and test and execute the policy. Once a policy is defined, we can either publish, deploy or un-deploy it. We can maintain multiple versions of a policy. 
  • Rules: Rules are the actual representation of business rules inside a policy. It contains data (facts), predicates, and actions. We can set the priority on each rule. 
  • Facts: Data that BRE operates against. 
  • Fact Source: Fact sources can be XML documents, database, or .NET objects. 

Functions
  • Assert: Assert is a way to insert facts into rule engine working memory at execution time. Assert function might cause rule execution cycle to repeat and it can also alter rule execution agenda. When a fact is added using Assert () function, rule execution cycle repeats itself and rules are reevaluated. 
  • Update: Indicates that a certain fact should be reevaluated, causing all rules using the fact to be reevaluated. In Assert, all of the rules are re-evaluated while in Update only those rules are re-evaluated where updated fact is either in predicate or in both action and predicate. 
  • Halt: Halt function to halts the current rule engine execution. 
Let’s start by creating a simple policy for performing a lookup on Product Code based on the Product Name received from the source system and we would test and integrate the policy inside a process. 

Open the Business Rule Composer by selecting Start->Programs->Microsoft BizTalk Server 2013->Business Rule Composer. 

Within the Policy Explorer, right-click the Policies node, and click Add New Policy. Give the policy name as BizTalkDJ.ProductCodeLookUp. 
By default, version 1.0 of the policy is created. 
Right-click the version, and choose Save. 
Right-click Version 1.0, and then click AddNewRule and rename it to Title. 

On the right pane of the rule, in the Condition pane (top) right-click choose Conditions, click on Predicates and then choose the applicable predicate (equal)



Now, in the Facts Explorer window, click the XML Schemas tab. 
Right-click Schemas, click Browse, and then select the OrderRequest.xsd file, browse and drag the ProductName node from the Facts Explorer window to argument1 in the Condition pane and in the Condition pane, click arugument2, provide the evaluating data (Title). On completing the condition in then action pane, drag the ProductCode node from the Facts Explorer window to the action pane at the bottom-right side of Business Rule Composer. Click <Enter a value> and then type look up code (TO). 



A policy can have one or more rules. You will be adding another rule, repeat these steps to create the rules for Escrow and Signing Products. And we can prioritize execution of rules by specifying the Priority property on rules in Business Rule Composer. For example, if you click the Title node in the Policy Explorer window, you can see the Priority property in the Properties window. The larger the number, the higher the rule priority. 


Test Policy 
We can unit test the policy by right-clicking on Version 1.0, and then choose Test Policy, in a Test Select Facts window, under XMLDocuments node, select OrderRequest, and then click on Add Instance to choose the input request to your policy.




Click Test. 

Invoking Policy in Orchestration

You can invoke a policy from an orchestration in one of the following ways: 
By using the Call Rules shape 

By using the Expression shape, and programmatically invoking the rule engine to execute the policy (Policy.Execute method) 

Using the Call Rules shape is the most common way and also the recommended way to invoke a policy from an orchestration. This is a simple process, where we would receive an order request; then execute the BRE policy to enrich the order request before sending to destination system. The orchestration should look like the following figure. 

Deploy and configure the application, then process order request and see the enriched output order request. 
Create Vocabulary
In the Facts Explorer window, click the Vocabularies tab. Right-click Vocabularies, click Add New Vocabulary, and then type BREConcept.OrderRequest as the name for the vocabulary. 

Right-click Version 1.0(not saved) in BREConcept.OrderRequest, and then click Add New Definition. 
In the Vocabulary Definition Wizard, select XML Document Element or Attribute, and then click Next. For the Definition name, type GetProductName. 
Click Browse, and select the OrderRequest.xsd file, in the Select Binding dialog box, expand OrderRequest and choose ProductName. Then specify the operation as Get. 


Similarly, repeat the steps to create vocabulary for ProductCode but this time, we would choose operation as Set. (You can play around the xpath), here I have modified the xpath as show in the table.

Original X-path Binding 

X-path Selector
/*[local-name()='OrderRequest' and namespace-uri()=‘‘]/*[local-name()='ProductList' and namespace-uri()=‘‘]/ *[local-name()='Product' and namespace-uri()=‘‘] 

X-path Field
*[local-name()='ProductCode' and namespace-uri()=‘‘] 

Modified X-path Binding 
X-path Selector
/*[local-name()='OrderRequest' and namespace-uri()=‘‘]/*[local-name()='ProductList' and namespace-uri()=‘‘]/ *[local-name()='Product' and namespace-uri()=‘‘]/*[local-name()='ProductCode' and namespace-uri()=‘‘] 

X-path Field

We can have multiple versions of a vocabulary and only the published vocabulary can be used in the policy. Both Policy and vocabulary can be exported/imported. 



Conclusion
In this article, I covered how to develop and integrate BRE policies with BizTalk Process. Now you can apply this solution to your own business scenario. 

The video demonstration is available on the Youtube, here is the embedded video.