2015-02-17 45 views
1

我試圖讓一個XML文件,看起來像:序列化xml文件的一部分。想的命名空間,根,而不是序列化的子元素

<RootLevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.MyCompany.com/MySchema.xsd"> 
    <Level1> 
     <Level2> 
     </Level2> 
    </Level1 > 
    <Level1> 
     <Level2> 
     </Level2> 
    </Level1 > 
    etc. repeats hundreds of times 
</RootLevel> 

我使用XSD.EXE工具生成從我的XML模式定義文件中的一些類。它們看起來像:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://MyCompany.com/MySchema.xsd")] 
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.MyCompany.com/MySchema.xsd", IsNullable = false)] 
public partial class RootLevel 
{ 
    private List<Level1> level1Field; 

    public List<Level1> Level1Field 
    { 
     get { return this.level1Field;} 
     set {this.level1Field = value;} 
    } 
} 

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.MyCompany.com/MySchema.xsd")] 
public partial class Level1 
{ 
    private List<Level2> level2Field; 

    public List<Level2> Level2Field 
    { 
     get { return this.level2Field;} 
     set {this.level2Field = value;} 
    } 

    /* other properties on Level1 go here*/ 
} 

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.MyCompany.com/MySchema.xsd")] 
public partial class Level2 
{ 
    /* properties on Level2 go here*/ 
}  

我寫了使用XmlWriter.WriteStartElement()的根層次Rootlevel元素使這個文件,然後我通過創建1級的對象,並與XmlSerializer的序列化他們寫出來的文件的其餘部分。

目標

我想要的文件只擁有根層次Rootlevel元素的命名空間。

如果你有興趣,這裏是我試過到目前爲止:

起點

在開始時,我的根層次Rootlevel元素沒有任何名稱空間。 我的Level1和Level2元素有名稱空間。

步驟1:

我試圖通過重寫在XmlTypeAttributes爲類Level1和Level2的命名空間去除Level1和Level2的元素的命名空間。

XmlTypeAttribute attribute = new XmlTypeAttribute(); 
attribute.Namespace = string.Empty; 

XmlAttributes attributes = new XmlAttributes(); 
attributes.XmlType = attribute; 

XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 
overrides.Add(typeof(Level1), attributes); 
overrides.Add(typeof(Level2), attributes); 

this.xmlSerializer = new XmlSerializer(typeof(Level1), overrides); 

步驟1結果

從級別2中除去命名空間而不是從級別1。

步驟2

增加了一些代碼,試圖從1級刪除的命名空間。我嘗試使用XmlSerializer.Serialize()方法的namespaces參數來使用空名稱空間。注意「level1」是「Level1」類型的對象。

XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); 
namespaces.Add("", ""); 

this.xmlSerializer.Serialize(this.xmlFileWriter, level1, namespaces); 

步驟2結果

的命名空間從兩個Level1和Level2除去。到現在爲止還挺好!現在我需要做的是將命名空間的內容添加到RootLevel。

步驟3

由於根層次Rootlevel未被序列,我添加了一些的XmlWriter代碼來嘗試添加命名空間根層次Rootlevel。

string defaultNamespace = "http://www.MyCompany.com/MySchema.xsd"; 
this.xmlFileWriter.WriteStartElement("RootLevel", defaultNamespace); 
this.xmlFileWriter.WriteAttributeString("xmlns", "xsi", "", "http://www.w3.org/2001/XMLSchema-instance"); 
this.xmlFileWriter.WriteAttributeString("xmlns", "xsd", "", "http://www.w3.org/2001/XMLSchema"); 

步驟3結果

的命名空間加入到根層次Rootlevel。好極了!。 但是,現在每個Level1元素都有一個xmlns =「」屬性。哎呀!

<RootLevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.MyCompany.com/MySchema.xsd"> 
    <Level1 xmlns=""> 
     <Level2> 
     </Level2> 
    </Level1 > 
    <Level1 xmlns=""> 
     <Level2> 
     </Level2> 
    </Level1 > 
    etc. repeats hundreds of times 
</RootLevel> 

那麼爲什麼會發生這種情況呢?

回答

0

你不發表您的原始代碼,所以我並不確切地知道你在哪裏錯了,但我能得到你想要的XML如下:

  1. 提取靜態輔助類XmlNamespaces保存命名空間字符串並將它們聲明爲const字符串。在你的問題中,你有時使用"http://MyCompany.com/MySchema.xsd",但有時使用"http://www.MyCompany.com/MySchema.xsd"。這可能只是一個錯誤的問題,但如果你的代碼使用這些不一致,這將導致錯誤。

  2. 除了應用XmlRootAttribute到類Level1XmlTypeAttribute

    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = XmlNamespaces.Default)] 
    [System.Xml.Serialization.XmlRootAttribute(Namespace = XmlNamespaces.Default, IsNullable = false)] 
    public partial class Level1 
    { 
        // Properties 
    } 
    
  3. 當寫入根元素,默認名稱空間字符串傳遞給XmlWriter.WriteStartElement(string, string)

總體代碼如下:

public static class XmlNamespaces 
{ 
    public const string Default = "http://MyCompany.com/MySchema.xsd"; 
    public const string xsi = "http://www.w3.org/2001/XMLSchema-instance"; 
    public const string xsd = "http://www.w3.org/2001/XMLSchema"; 

    public static XmlSerializerNamespaces XmlSerializerNamespaces 
    { 
     get 
     { 
      var namespaces = new XmlSerializerNamespaces(); 
      namespaces.Add("", XmlNamespaces.Default); 
      namespaces.Add("xsi", XmlNamespaces.xsi); 
      namespaces.Add("xsd", XmlNamespaces.xsd); 
      return namespaces; 
     } 
    } 
} 

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = XmlNamespaces.Default)] 
[System.Xml.Serialization.XmlRootAttribute(Namespace = XmlNamespaces.Default, IsNullable = false)] // Added this and used const string from XmlNamespaces class 
public partial class Level1 
{ 
    private List<Level2> level2Field; 

    public List<Level2> Level2Field 
    { 
     get { return this.level2Field; } 
     set { this.level2Field = value; } 
    } 

    /* other properties on Level1 go here*/ 
} 

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = XmlNamespaces.Default)] // Used const string from XmlNamespaces class 
public partial class Level2 
{ 
    /* properties on Level2 go here*/ 
} 

public static class XmlSerializationUtilities 
{ 
    public static void WriteList<TItem>(string rootName, XmlSerializerNamespaces namespaces, IEnumerable<TItem> list, TextWriter textWriter) 
    { 
     var namespaceList = namespaces.ToArray(); 
     string defaultNamespace = null; 
     foreach (var ns in namespaceList) 
     { 
      if (string.IsNullOrEmpty(ns.Name)) 
      { 
       defaultNamespace = ns.Namespace; 
       break; 
      } 
     } 

     var settings = new XmlWriterSettings(); 
     settings.Indent = true; 
     settings.IndentChars = " "; 

     using (var writer = XmlWriter.Create(textWriter, settings)) 
     { 
      writer.WriteStartDocument(); 
      writer.WriteStartElement(rootName, defaultNamespace); 

      foreach (var ns in namespaceList) 
       if (!string.IsNullOrEmpty(ns.Name)) 
        writer.WriteAttributeString("xmlns", ns.Name, null, ns.Namespace); 

      var serializer = new XmlSerializer(typeof(TItem)); 
      foreach (var item in list) 
      { 
       serializer.Serialize(writer, item); 
      } 

      writer.WriteEndElement(); 
      writer.WriteEndDocument(); 
     } 
    } 
} 

public static class TestClass 
{ 
    public static void Test() 
    { 
     var list = new List<Level1> { new Level1 { Level2Field = new List<Level2> { new Level2(), new Level2() } }, new Level1 { Level2Field = new List<Level2> { new Level2(), new Level2(), new Level2(), new Level2() } } }; 

     string xml; 

     using (var writer = new StringWriter()) 
     { 
      XmlSerializationUtilities.WriteList("RootLevel", XmlNamespaces.XmlSerializerNamespaces, list, writer); 
      xml = writer.ToString(); 

      Debug.WriteLine(xml); 
     } 
    } 
} 

,輸出是

<?xml version="1.0" encoding="utf-16"?> 
<RootLevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://MyCompany.com/MySchema.xsd"> 
    <Level1> 
     <Level2Field> 
      <Level2 /> 
      <Level2 /> 
     </Level2Field> 
    </Level1> 
    <Level1> 
     <Level2Field> 
      <Level2 /> 
      <Level2 /> 
      <Level2 /> 
      <Level2 /> 
     </Level2Field> 
    </Level1> 
</RootLevel> 
+0

OK,我編輯我原來的職位所以它總是說www.MyCompany.com。 – cbast 2015-02-24 19:53:02

+1

在閱讀您的文章後,它似乎是解決我的問題的關鍵是將XmlRootAttribute添加到Level1類。 – cbast 2015-02-24 19:53:38

+1

我不知道我可以在我的RootLevel和Level1類上使用XmlRootAttribute。通過這樣做,我能夠刪除我想要覆蓋命名空間內容的所有代碼。 – cbast 2015-02-24 20:03:03