2012-01-11 13 views
4

"サービス参照の追加..."操作でオブジェクトが生成されました。これを手作業でシリアライザでシリアル化しています。シリアライザで作成された空のxmlnsを削除します

私の問題は、データコントラクトに内部オブジェクトがいくつかあることです。

シリアライザは、空の名前空間atributeを内部オブジェクトの開始タグに追加します。これが起こるのを止める方法はありますか?

+5

なぜそれが問題ですか?要素がデフォルト名前空間にある場合、 'xmlns =" "'は正しいです。 –

+0

xmlns = ""は正しいかもしれませんが、私はこれを受け取ったWSのコントロールを持っていません。どのような方法でそれらを削除するには? –

+0

xmlns = "" XMLを読んでいるコードが壊れていると、ひどく壊れていて、修正が必要な非常に悪いバグがあります。いくつかの基本的な正しいXMLを読むことに失敗しています。良い隣人であることを確実にして、そのコードの所有者にデフォルトの名前空間を処理するように修正する必要があることを伝えます。 –

答えて

6

何がルートと同じ名前空間に属していますか?そうすれば、子孫からxmlns宣言を省略することが正しいでしょう。 [assembly: ContractNamespace]属性を使用して、アセンブリ内のすべてのコントラクトの名前空間をオーバーライドできます。例はData Contract Namesを参照してください。

編集:下記のいくつかの例を参考にしてください。

XML文書を手動で構築していて、いずれの要素にも名前空間を指定していないとします。

<Book> 
    <Title>Animal Farm</Title> 
    <Author>George Orwell</Author> 
    <Publisher> 
    <Name>Secker and Warburg</Name> 
    <Location>London</Location> 
    <Founded>1910</Founded> 
    </Publisher> 
</Book> 

しかし、あなたは、すべての子要素を明示的に元に戻す必要があり、ちょうどあなたのルート要素の名前空間を指定し、場合:生成されたXMLは、予想通り、名前空間宣言の空隙だろう

XDocument xmlDocument = new XDocument(
    new XElement("Book", 
     new XElement("Title", "Animal Farm"), 
     new XElement("Author", "George Orwell"), 
     new XElement("Publisher", 
      new XElement("Name", "Secker and Warburg"), 
      new XElement("Location", "London"), 
      new XElement("Founded", 1910)))); 
return xmlDocument.ToString(); 

その既定の名前空間のxml=""宣言を使用します。デフォルトの名前空間宣言は、任意の内側のデフォルトの名前空間宣言のスコープを除いて、対応する終了タグの最後にそれが現れる開始タグの始まりから延びているの

範囲:Namespace Defaultingルールあたり。空のタグの場合、スコープはタグそのものです。したがって

、次のコード(ルート要素のために指定された名前空間を持つ)...

XDocument xmlDocument = new XDocument(
    new XElement("{http://example.com/library}Book", 
     new XElement("Title", "Animal Farm"), 
     new XElement("Author", "George Orwell"), 
     new XElement("Publisher", 
      new XElement("Name", "Secker and Warburg"), 
      new XElement("Location", "London"), 
      new XElement("Founded", 1910)))); 
return xmlDocument.ToString(); 

...次のXML与えるだろう:どのように<Publisher>の子供

<Book xmlns="http://example.com/library"> 
    <Title xmlns="">Animal Farm</Title> 
    <Author xmlns="">George Orwell</Author> 
    <Publisher xmlns=""> 
    <Name>Secker and Warburg</Name> 
    <Location>London</Location> 
    <Founded>1910</Founded> 
    </Publisher> 
</Book> 

注意を要素は、親から「名前空間なし」の宣言を継承するため、ルートの名前空間から復帰する必要はありません。

xmlns=""宣言を排除するために、我々は、デモンストレーションのために、すべての子孫に同じ名前空間を割り当てることができます:

XDocument xmlDocument = new XDocument(
    new XElement("{http://example.com/library}Book", 
     new XElement("{http://example.com/library}Title", "Animal Farm"), 
     new XElement("{http://example.com/library}Author", "George Orwell"), 
     new XElement("{http://example.com/library}Publisher", 
      new XElement("{http://example.com/library}Name", "Secker and Warburg"), 
      new XElement("{http://example.com/library}Location", "London"), 
      new XElement("{http://example.com/library}Founded", 1910)))); 
return xmlDocument.ToString(); 

これは(ちょうどルートに宣言された名前空間を持つXML文書を与えるだろうそして、暗黙のうちにすべての子孫)に継承された:Webサービスを含む、あなたのシナリオを模倣するために

<Book xmlns="http://example.com/library"> 
    <Title>Animal Farm</Title> 
    <Author>George Orwell</Author> 
    <Publisher> 
    <Name>Secker and Warburg</Name> 
    <Location>London</Location> 
    <Founded>1910</Founded> 
    </Publisher> 
</Book> 

、我々は以下のWCFサービスを作成することができます。

[DataContract] 
public class Book 
{ 
    [DataMember] 
    public string Title { get; set; } 
    [DataMember] 
    public string Author { get; set; } 
    [DataMember] 
    public Publisher Publisher { get; set; } 
} 

[DataContract] 
public class Publisher 
{ 
    [DataMember] 
    public string Name { get; set; } 
    [DataMember] 
    public string Location { get; set; } 
    [DataMember] 
    public short Founded { get; set; } 
} 

[ServiceContract] 
public interface ILibraryService 
{ 
    [OperationContract] 
    Book GetBook(); 
} 

public class LibraryService : ILibraryService 
{ 
    public Book GetBook() 
    { 
     return new Book 
     { 
      Title = "Animal Farm", 
      Author = "George Orwell", 
      Publisher = new Publisher 
      { 
       Name = "Secker and Warburg", 
       Location = "London", 
       Founded = 1910, 
      } 
     }; 
    } 
} 

私たちは、私たちのクライアントアプリケーションで上記のサービスへのサービス参照を追加しその動作を消費し、明示的な名前空間の持つルートBooks要素で囲んながら結果をシリアライズ:で

using (var libraryClient = new LibraryServiceReference.LibraryServiceClient()) 
{ 
    var book = libraryClient.GetBook(); 

    var stringBuilder = new StringBuilder(); 
    using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder)) 
    { 
     xmlWriter.WriteStartElement("Books", "http://example.com/library"); 
     var serializer = new XmlSerializer(book.GetType()); 
     serializer.Serialize(xmlWriter, book); 
     xmlWriter.WriteEndElement(); 
    } 

    return stringBuilder.ToString(); 
} 

をこの場合、内部要素Bookにはxmlns=""宣言が含まれています。

<?xml version="1.0" encoding="utf-16"?> 
<Books xmlns="http://example.com/library"> 
    <Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
     xmlns=""> 
    <ExtensionData /> 
    <Author>George Orwell</Author> 
    <Publisher> 
     <ExtensionData /> 
     <Founded>1910</Founded> 
     <Location>London</Location> 
     <Name>Secker and Warburg</Name> 
    </Publisher> 
    <Title>Animal Farm</Title> 
    </Book> 
</Books> 

。上述のように、このxmlns=""は、ルートのに対応してBook要素の名前空間を設定することにより、除去(およびその子孫のこと)することができます。 XmlSerializerクラスの場合、すべての要素のデフォルト名前空間は、そのコンストラクタの2番目のパラメータによって指定できます。 (実際の技術はどのあなたが使用しているシリアル化戦略によって異なります。)

using (var libraryClient = new LibraryServiceReference.LibraryServiceClient()) 
{ 
    var book = libraryClient.GetBook(); 

    var stringBuilder = new StringBuilder(); 
    using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder)) 
    { 
     xmlWriter.WriteStartElement("Books", "http://example.com/library"); 
     var serializer = new XmlSerializer(book.GetType(), "http://example.com/library"); 
     serializer.Serialize(xmlWriter, book); 
     xmlWriter.WriteEndElement(); 
    } 

    return stringBuilder.ToString(); 
} 

そして、それは期待した結果与えるだろう:

<?xml version="1.0" encoding="utf-16"?> 
<Books xmlns="http://example.com/library"> 
    <Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <ExtensionData /> 
    <Author>George Orwell</Author> 
    <Publisher> 
     <ExtensionData /> 
     <Founded>1910</Founded> 
     <Location>London</Location> 
     <Name>Secker and Warburg</Name> 
    </Publisher> 
    <Title>Animal Farm</Title> 
    </Book> 
</Books> 
+0

XmlSerializerの代わりにデータコントラクトシリアライザを使用しました。これにより、すぐに使えるようになりましたが、答えに感謝します。バウンティは得た。 –

+1

ありがとう! :-)私は 'DataContractSerializer'について言及するつもりでしたが、私は(誤って)サービス自体がデータコントラクトのための空の(または間違った)名前空間を宣言していたと想定していました(例えば[DataContract(Namespace =" ")])。そのシリアライザでクライアント側で回避することは容易ではありません。 'XmlSerializer'は、データコントラクト上で宣言された名前空間を無視し、あなた自身の代わりに使うことができます。とにかく、あなたは簡単な解決策を見つけてうれしいです! – Douglas

0

シリアライザを制御できる場合は、常にxmlnsが出力XMLから省略されるようにnull名前空間を追加できます。例えば:

var serializer = new XmlSerializer(target.GetType()); 
var ns = new XmlSerializerNamespaces(); 
ns.Add("",""); 
serializer.Serialize(xmlWriter, target, ns); 

敬具、あなたの内部オブジェクトを作る程度

+0

私はそれを試みましたが、すべての要素からxmlnsを削除します。私はまだxmlns(これは空ではない)を持つためにはrootが必要です。 –

0

これは少しオフトピックこととない場合がありますが[DataContract]を使用している場合は適用します。むしろ、これはWSDLから生成されたプロキシコードに適用されます(Javaエンドポイントを持つ相互運用環境では、xmlns = ""は無効です)。だから私はそれが助けになる場合にそれを出している。

に設定すると、XmlElementAttribute.Formプロパティでは、WCF要求の子メンバーに対してxmlns = ""が出力される可能性があります。 (デフォルト値である)System.Xml.Schema.XmlSchemaForm.Noneに設定

<MyObject xmlns="http://some.namespance"> 
    <MyProperty xmlns="">My value goes here</MyProperty> 
</MyObject> 

の線に沿って何かを作り出す

[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] 
public string MyProperty { 
    get; set; 
} 

は、それが出力する「非修飾」名前空間属性をしないことを意味します。

これを生成
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.None)] 
public string MyProperty { 
    get; set; 
} 

<MyObject xmlns="http://some.namespance"> 
    <MyProperty>My value goes here</MyProperty> 
</MyObject> 

私は、WSDLの参照をインポートするときは、この動作を変更できるかどうかわからない、またはおそらくWSDLが変更されている必要がありますが、私が編集してしまいました(これは間違いなく理想的ではない)プロキシコードを直接生成したが、私の直ちに目標を達成した。

関連する問題