BizTalk: Maps mit Referenzen zu externen Assemblies debuggen

by wolfgang@gehirnwindung.de (Wolfgang) Mai 05, 2010 14:25

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...

Kommentare

05.05.2010 15:51:08 #

trackback

BizTalk: Maps mit Referenzen zu externen Assemblies debuggen

Sie wurden gekickt (eine gute Sache) - Trackback von  dotnet-kicks.de

dotnet-kicks.de |

20.08.2010 10:04:17 #

Albert

Vielen Dank für deine Mühe. Hat mir geholfen mein XSLT genau verfolgen zu können.
Ich würd aber noch gerne wissen ob deine Methode auch eine Output-XML generiert, die ich nicht finden kann, oder ob ich den Output selbst noch erzeugen muss?

Albert Deutschland |

02.10.2010 16:41:45 #

Wolfgang

Hallo,
der Output wird auch generiert - im obigen Beispiel aber innerhalb eines Null-TextWriters, und damit im Nirvana.

Allerdings sieht man beim Debuggen auch die Ausgabe (in dem Moment, in dem ein Element/Attribut/Wert geschrieben wird, erscheint dieser auch in der Ausgabe)... Wenn nichts geändert wurde, passiert das in einem Fenster rechts neben dem xsl-Dokument (erscheint erst beim Debuggen)

Viele Grüße, Wolfgang

Wolfgang Deutschland |

Kommentare sind geschlossen

Powered by BlogEngine.NET 1.6.1.6
Theme by Mads Kristensen | Modified by Mooglegiant and me ;)