1

デバッチ処理が必要な着信XMLメッセージに名前空間を追加するための推奨される方法は何ですか?着信XMLメッセージのバッチを解除するために、エンベロープと「通常の」メッセージxsdスキーマを使用しています。どちらもターゲット名前空間を持っています。着信XMLメッセージには、そもそも名前空間が付加されていません。

ありがとうございました

using System;
using System.Linq;
using System.Xml.Linq;

public class AddNamespaceRcvPipelineComponent
{
    static public void Main ()
    {
        XElement xDoc = XElement.Load(@"test.xml");

        XNamespace ns1 = "Namespace1";
        XNamespace ns2 = "Namespace2";

        foreach (XElement el in xDoc.DescendantsAndSelf("ORDERS"))
        {
            // el.Add(new XAttribute(XNamespace.Xmlns + "ns1", "Namespace1"));
            el.Name = ns1 + el.Name.LocalName;
        }

        foreach (XElement el in xDoc.DescendantsAndSelf("ORDER"))
        {
            // el.Add(new XAttribute(XNamespace.Xmlns + "ns2", "Namespace2"));
            el.Name = ns2 + el.Name.LocalName;
        }

        // TODO: Strip empty namespaces ...

        Console.WriteLine(xDoc);
    }
}
4

2 に答える 2

2

問題を解決するための標準的な方法は、実際、着信パイプラインのデコード段階でカスタムパイプラインコンポーネントを使用することです。

これを効率的に機能させるための2つの方法があります。

BizTalkESBTookitパイプラインコンポーネントの使用

BizTalk ESB Toolkit 2.1には、着信メッセージのXML名前空間を操作するための非常に強力なパイプラインコンポーネントのセットがあります。このパイプラインは、Microsoft.Practices.ESB.Namespace.PipelineComponents.dllアセンブリ利用でき、インストール時にVisualStudioツールボックスで利用できるようになります。

これらのコンポーネントの以前のバージョンは、MSDNに記載されています。このドキュメントはかなり古くなっていますが、新しいバージョンでは何も変わっていないと思います。それでも、適切な使用法と参照については、さまざまなフォーラムの質問を参照することをお勧めします。

単純なAddXmlNamespaceパイプラインコンポーネントの構築

ご使用の環境にBizTalkESBToolkitをインストールしたくない、またはインストールできない場合は、コンポーネントの簡略化されたバージョンを自分で作成することをお勧めします。活用できるBizTalkランタイムの組み込みクラスのおかげで、それはまったく難しいことではありません。

質問で示したコードは、適切なストリーミング対応のパイプラインコンポーネントに準拠していないため、以下に必要なコードを示しています。以下に示すコードは、元のルートタグにXML名前空間がまだ存在しない場合は、それを追加することのみを扱っていることに注意してください。

まず、元のドキュメントのルートタグにXML名前空間とプレフィックスを追加することを処理する単純なSystem.IO.Streamから派生したクラスを構築する必要があります。

ストリーミングをサポートするために、コードはMicrosoft.BizTalk.Streaming.XmlTranslatorStreamクラスを利用します。このクラスはSAXのようなインターフェースを示し、XML解析段階のさまざまなポイントで実装のオーバーライドが呼び出されます。これらはすべて、任意の大きなドキュメントのストリーミングを完全にサポートしながら実行されます。

これはコードです:

using Microsoft.BizTalk.Streaming;

public class AddXmlNamespaceStream : XmlTranslatorStream
{
    private String namespace_;
    private int level_ = 0; // hierarchy level

    public AddXmlNamespaceStream(Stream stream, String @namespace)
        : base(XmlReader.Create(stream))
    {
        namespace_ = @namespace;
    }

    #region XmlTranslatorStream Overrides

    protected override void TranslateStartElement(string prefix, string localName, string nsURI)
    {
        if (level_++ != 0)
        {
            base.TranslateStartElement(prefix, localName, nsURI);
            return;
        }

        if (String.IsNullOrEmpty(nsURI))
        {
            nsURI = namespace_;
            if (String.IsNullOrEmpty(prefix))
                prefix = "__bts_ns0__";
        }

        base.TranslateStartElement(prefix, localName, nsURI);
    }

    protected override void TranslateEndElement(bool full)
    {
        if (level_-- != 0)
        {
            base.TranslateEndElement(full);
            return;
        }

        base.TranslateEndElement(full);
    }

    #endregion
}

このクラスはTranslateStartElementメソッドとTranslateEndElementメソッドの両方をオーバーライドしますが、階層の最初のレベル(ルートタグ)の要素のみを処理することに気付くでしょう。他のすべての要素は、基本クラスによって提供されるデフォルトの何もしない特別な動作に従って処理されます。

パイプラインコンポーネント自体については、必要なボイラープレートインフラストラクチャコードをすべてすでにセットアップしている可能性があるため、ここではExecuteメソッドのみを示します。そうでない場合は、下から順に次の場所にあるブログ投稿を参照してください。

ここにあります:

public class AddXmlNamespace : ..., IComponent
{
    #region Design-Time Properties

    public String Namespace { get; set; }

    #endregion

    #region IComponent Implementation

    public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
    {
        var stream = new AddXmlNamespaceStream( 
            pInMsg.BodyPart.GetOriginalDataStream()
            , Namespace);

        pInMsg.BodyPart.Data = stream;
        pContext.ResourceTracker.AddResource(stream);

        return pInMsg;
    }

    #endregion

    ...
}

ご覧のとおり、Executeメソッドによって実行される唯一のアクションは、元のストリームを新しいAddXmlNamespaceストリームクラスのインスタンスでラップし、着信メッセージストリームを置き換えるように接続することです。

お役に立てれば。

于 2012-05-21T16:32:24.663 に答える
0

ESBツールキットには、これを行うパイプラインコンポーネントがあります。

于 2012-05-18T08:11:51.940 に答える