by community-syndication | Jun 24, 2014 | BizTalk Community Blogs via Syndication
Well
not a bad one to track down and basically from reverse engineering the Microsoft.BizTalk.Pipeline.Comonents.dll your
xpath expressions need to be in the a ‘certain format’ even though the traditional
Xpath tools work beautifully.
I
was dealing with some HL7 messages so my call stack maybe slightly different to yours
– but it’s something like:
Fatal
error encountered in 2XDasm. Exception information is Microsoft.BizTalk.Component.ComponentException
at Microsoft.BizTalk.Component.XPathHelper.CheckXPathExpression(String strXPath)
at Microsoft.BizTalk.Component.XPathDenormalizer.Denormalize(String xpath, Boolean
bAbsolute, Boolean bGetChildNodes)
at Microsoft.BizTalk.Component.XmlDasmReader.CreateReader(IPipelineContext pipelineContext,
IBaseMessageContext messageContext, MarkableForwardOnlyEventingReadStream data, Encoding
encoding, Boolean saveEnvelopes, Boolean allowUnrecognizedMessage, Boolean validateDocument,
SchemaList envelopeSpecNames, SchemaList documentSpecNames, IFFDocumentSpec docSpecType,
SuspendCurrentMessageFunction documentScanner)
at Microsoft.BizTalk.Component.XmlDasmReader.CreateReader(IPipelineContext pipelineContext,
IBaseMessageContext messageContext, MarkableForwardOnlyEventingReadStream data, Encoding
encoding, Boolean saveEnvelopes, Boolean allowUnrecognizedMessage, Boolean validateDocument,
SchemaList envelopeSpecNames, SchemaList documentSpecNames)
at Microsoft.Solutions.BTAHL7.Pipelines.HL72fDasm.ParseMessageBody(IPipelineContext
pc, ArrayList& xmlErrors, Boolean& fatalError)
at Microsoft.Solutions.BTAHL7.Pipelines.HL72fDasm.ProcessIndividualMessage(IPipelineContext
pc)
at Microsoft.Solutions.BTAHL7.Pipelines.HL72fDasm.ProcessChunkedMessages(IPipelineContext
pc)
at Microsoft.Solutions.BTAHL7.Pipelines.HL72fDasm.GetNext(IPipelineContext pc)
Microsoft.BizTalk.Component.XPathHelper.CheckXPathExpression(String
strXPath) is
the main culprit.
From
my reverse engineering efforts I tracked the problem down to the result of this method
call:
namespace Microsoft.BizTalk.Component
{
internal sealed class XPathHelper
{
private XPathHelper()
{
}
public static void CheckXPathExpression(string strXPath)
{
if (XPathCanonizer.Canonize(strXPath, true)
== null)
{
string empty = string.Empty;
string[]
strArrays = new string[]
{ strXPath };
throw new ComponentException((uint)-1061153675,
empty, strArrays);
}
}
}
}
//Here’s
essentially the code the above line calls –
public class CanonicalXPath
{
private XPathExpression
_xpath;
private bool _ignoreNS;
public XPathExpression
XPathExpression
{
get
{
return this._xpath;
}
}
internal CanonicalXPath(string xpath, bool ignoreNS)
{
this._ignoreNS = ignoreNS;
XPathExpression
xPathExpression = new XPathExpression(xpath);
StringBuilder
stringBuilder = new StringBuilder();
IQuery[]
expression = xPathExpression.GetExpression();
for (int i = 0;
i < (int)expression.Length;
i++)
{
IQuery
query = expression[i];
if (query is NullQuery)
{
break;
}
stringBuilder.Append(“/”);
XPathCanonizer.XPathCanonizerState.CanonicalXPath.StepCanonizer
stepCanonizer = new XPathCanonizer.XPathCanonizerState.CanonicalXPath.StepCanonizer(this,
query);
stringBuilder.Append(stepCanonizer.Process());
}
this._xpath = new XPathExpression(stringBuilder.ToString());
}
private class StepCanonizer
{
private readonly XPathCanonizer.XPathCanonizerState.CanonicalXPath
_owner;
private readonly StringBuilder
_sb;
private readonly IQuery
_toplevelQuery;
private string _name;
private string _namespace;
private bool _isAttribute;
public StepCanonizer(XPathCanonizer.XPathCanonizerState.CanonicalXPath
owner, IQuery stepQuery)
{
this._owner = owner;
this._sb = new StringBuilder();
this._toplevelQuery = stepQuery;
}
private void _generate()
{
if (this._isAttribute)
{
this._sb.Append(“@”);
}
this._sb.AppendFormat(“*[local-name()='{0}'”, this._name);
if (this._namespace
!= null)
{
this._sb.AppendFormat(”
and namespace-uri()='{0}'”, this._namespace);
}
this._sb.AppendFormat(“]”, this._name);
}
private void _processAxis(BaseAxisQuery
axisQuery)
{
if (!string.IsNullOrEmpty(axisQuery.Prefix))
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
switch (axisQuery.NodeType)
{
case XPathNodeType.Element:
{
this._isAttribute = false;
break;
}
case XPathNodeType.Attribute:
{
this._isAttribute = true;
break;
}
default:
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
}
string name = axisQuery.Name;
if (!string.IsNullOrEmpty(name))
{
this._name = name;
this._namespace = string.Empty;
}
}
private void _processFilter(FilterQuery
fq)
{
this._processAxis(fq.Axis);
this._processPredicate(fq.Predicate);
}
private void _processPredicate(IQuery
q)
{
Type
type = q.GetType();
if (type
== typeof(AndExpr))
{
AndExpr
andExpr = q as AndExpr;
this._processPredicate(andExpr.LeftOperand);
this._processPredicate(andExpr.RightOperand);
return;
}
if (type
== typeof(BooleanFunctions))
{
this._processPredicate((q as BooleanFunctions).BaseQuery);
return;
}
if (type
!= typeof(LogicalExpr))
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
LogicalExpr
logicalExpr = q as LogicalExpr;
if (logicalExpr.OperatorName
!= “EQ”)
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
IQuery
leftOperand = logicalExpr.LeftOperand;
IQuery
rightOperand = logicalExpr.RightOperand;
if (leftOperand is OperandQuery)
{
IQuery
query = leftOperand;
leftOperand = rightOperand;
rightOperand = query;
}
if (!(leftOperand is MethodOperand)
|| !(rightOperand is OperandQuery))
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
MethodOperand
methodOperand = leftOperand as MethodOperand;
object str = (rightOperand as OperandQuery).GetValue(null).ToString();
string functionName = methodOperand.FunctionName;
string str1 = functionName;
if (functionName
!= null)
{
if (str1
== “FuncNameSpaceUri”)
{
string str2 = (string)str;
if (this._namespace
!= null && this._namespace
!= str2)
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
this._namespace = str2;
return;
}
if (str1
== “FuncLocalName”)
{
string str3 = (string)str;
if (str3
== null ||
str3.Length == 0)
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
if (this._name
!= null && this._name
!= str3)
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
this._name = str3;
return;
}
}
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
private void _validate()
{
if (this._name
== null || this._name.Length
== 0)
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
if (this._namespace
== null &&
!this._owner._ignoreNS)
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
}
public string Process()
{
Type
type = this._toplevelQuery.GetType();
if (type
== typeof(FilterQuery))
{
this._processFilter(this._toplevelQuery as FilterQuery);
}
else if (type
!= typeof(ChildrenQuery))
{
if (type
!= typeof(AttributeQuery))
{
throw new XPathCanonizer.XPathCanonizerState.XPathCanonizationException();
}
this._processAxis(this._toplevelQuery as BaseAxisQuery);
}
else
{
this._processAxis(this._toplevelQuery as BaseAxisQuery);
}
this._validate();
this._generate();
return this._sb.ToString();
}
}
}
Write
a small test app:
1)
Open VS.NET and create a console app
2)
Reference – c:\program files\microsoft biztalk server XXXX\pipeline components\Microsoft.XLangs.RuntimeTypes.dll
2.1) Reference from the GAC – C:\Windows\assembly\GAC_MSIL\Microsoft.BizTalk.XPathReader\<your
version>\Microsoft.BizTalk.XPathReader.dll
Here’s
my sample code – I’m still working through making my XPath compliant:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.XLANGs.RuntimeTypes;
using Microsoft.BizTalk.XPath;
namespace XpathExpressionTester
{
class Program
{
static void Main(string[]
args)
{
var
strFailed = “/*/*[local-name()=’PRD_ProviderData’]/*[local-name()=’PRD_1_ProviderRole’]/*[local-name()=’CE_0286_0_Identifier’][text()=’RT’]/../../*[local-name()=’PRD_7_ProviderIdentifiers’]”;
var
strGood = “/*[local-name()=’Fred’]/*[local-name()=’PRD_ProviderData’]/*[local-name()=’PRD_1_ProviderRole’]/*[local-name()=’CE_0286_0_Identifier’][2]”;//[text()=’RT’]”;
// /../../*[local-name()=’PRD_7_ProviderIdentifiers’]”;
//var
strGood = “/*[local-name()=’Fred’]/*[local-name()=’PRD_ProviderData’]/*[local-name()=’PRD_1_ProviderRole’]/*[local-name()=’CE_0286_0_Identifier’
and text()=’RT’]/../../*[local-name()=’PRD_7_ProviderIdentifiers’]”;
var
xp = new XPathExpression(strGood);
Console.WriteLine(“We
got {0}”,
xp.GetExpression().Count());
RunTest(strFailed);
RunTest(strGood);
Console.ReadLine();
}
private static void RunTest(string str)
{
XPathExpression
result = XPathCanonizer.Canonize(str, true);
if (result
!= null)
Console.WriteLine(“We
got {0}”,
result.XPath);
else
Console.WriteLine(“BoomBoom
– we failed”);
}
}
}
Blog Post by: Mick Badran