Um BizTalk-Maps zu debuggen, die eine exterene Assembly aufrufen, reichen die Standard-Möglichkeiten nicht mehr aus. Es erscheint die Fehlermeldung
Cannot find the script or external object that implements prefix 'http://schemas.microsoft.com/BizTalk/2003/ScriptNS0'
Um das zu umgehen, müssen die externen Assemblies dem Debugger bekannt gemacht werden. Um allgemein XSLT zu debuggen kann, neben der Möglichkeit dies über das Menü "XML" -> "Debug XSLT" zu erledigen, auch das Objekt XslCompiledTransform verwendet werden. Hierdurch ist man wesentlich flexibler und kann z.B. StartParameter angeben und/oder eben Extension Objects". Und da eine BizTalk-Map letztendlich auch nur ein XSLT-Dokument darstellt, gilt das auch dafür.
Als erstes sollte man ein C#-Projekt zur BizTalk-Solution hinzufügen. Darin wird lediglich unten stehende Methode eingefügt und die "Main"-Methode so angepasst, dass ein Aufruf der Methode "DebugXslt" mit den jeweiligen Parametern erfolgt.
/// <summary>
/// Helper Method to debug Maps with Extension Objects
/// </summary>
/// <param name="mapXslt">Path to xslt-file generated by the MapperCompiler (Validate Map)</param>
/// <param name="inputXml">Path to input-file (Test Map)</param>
/// <param name="extensionObjectsXml">Path to Extension Object XML (Validate Map)</param>
static void DebugXslt( string mapXslt, string inputXml, string extensionObjectsXml ) {
if( !string.IsNullOrEmpty( mapXslt ) && !string.IsNullOrEmpty( inputXml ) && File.Exists( mapXslt ) && File.Exists( inputXml ) ) {
XslCompiledTransform xslt = new XslCompiledTransform( true );
// allow embedded scripts and document()-function
XsltSettings xsltSettings = new XsltSettings( true, true );
// Load the style sheet.
xslt.Load( mapXslt, xsltSettings, null );
// resolve extension objects
XsltArgumentList xsltArgs = new XsltArgumentList( );
if( !string.IsNullOrEmpty(extensionObjectsXml) && File.Exists( extensionObjectsXml ) ) {
XmlReaderSettings rsettings = new XmlReaderSettings( );
rsettings.IgnoreComments = true;
rsettings.IgnoreProcessingInstructions = true;
rsettings.IgnoreWhitespace = true;
using( XmlReader reader = XmlReader.Create( extensionObjectsXml, rsettings ) ) {
reader.ReadStartElement( "ExtensionObjects" );
do {
string ns = "", an = "", cn = "";
while( reader.MoveToNextAttribute( ) ) {
switch( reader.LocalName ) {
case "Namespace":
reader.ReadAttributeValue( );
ns = reader.Value;
break;
case "AssemblyName":
reader.ReadAttributeValue( );
an = reader.Value;
break;
case "ClassName":
reader.ReadAttributeValue( );
cn = reader.Value;
break;
}
}
// load type and add instance to xslt-Arguments
if( !string.IsNullOrEmpty( ns ) && !string.IsNullOrEmpty( an ) && !string.IsNullOrEmpty( cn ) ) {
Type t = Type.GetType( Assembly.CreateQualifiedName( an, cn ) );
xsltArgs.AddExtensionObject( ns, System.Activator.CreateInstance( t, false ) );
}
} while( reader.ReadToNextSibling( "ExtensionObject" ) );
reader.Close( );
}
}
// Execute the transformation.
using( XmlWriter writer = XmlWriter.Create( TextWriter.Null ) ) {
xslt.Transform( inputXml, xsltArgs, writer );
writer.Close( );
}
xsltArgs.Clear( );
}
}
| Parameter |
Beschreibung |
| mapXslt |
Pfad zur XSLT-Datei |
| inputXml |
Pfad zur der Datei, die die Testdaten enthält |
| extensionObjectsXml |
Pfad zur Datei, in der die Erweiterungsobjekte stehen (darf leer sein)
|
Nun müssen noch die einzelnen Pfade ermittelt werden. Mittels "Validate Map" (rot im Bild) werden die XSLT-Datei und die extensionObjects-Datei erstellt. Im Output-Window erscheinen die jeweiligen Pfade und müssen nur noch übernommen werden.
Hat man kein XML-Dokument, mit dem man Testen kann, sondern ein natives Format, so hilft "Test Map". Auch hier erscheint im Output-Window der Pfad mit dem Hinweis "Test Map used the following file".

Sind nun alle 3 Pfade ermittelt und eingetragen, kann es auch endlich losgehen. Damit der Debugger nicht einfach durchläuft, sollte die XSLT-Datei geöffnet und eine Haltepunkt eingefügt werden.

Nun muss das Projekt gestartet werden. Dazu mit der rechten Maustaste auf das Projekt zeigen und "Debug" -> "Start new instance" ausführen.
Alternativ das Projekt als StartUp-Project einrichten und F5 drücken...
