2015-10-02 12 views
10

Bir XSD oluşturulan otomatik, C# sınıfları, bir demet. Sonra bu C# sınıflarına dayalı XML dosyaları üretiyorum. Şimdiye kadar hiçbir şey mevcut değil.Ben XSD C# oluşturulan sınıfın yarattığı XML aynı etiketine boş niteliği ve diğer özelliği olabilir mi?

sorun:

oluşturulan XML dosyaları doğrulama geçiyor ve doğrulama xsi:nil="true" ile tüm XML etiketleri fazladan özelliğinin kullanılmasını gerektirir. Temel olarak etiketler şu şekilde görünmelidir: <testTag.01 xsi:nil="true" NV="123123" />, ancak bunu C# ile başaramıyorum. Benim kodudur:

 if (myObject.TestTag.HasValue) 
     { 
      t.testTag01 = new testTag01(); 
      t.testTag01.Value = myObject.TestTag.Value; 
     } 
     //else 
     //{ 
     // t.testTag01 = new testTag01(); 
     // t.testTag01.NV = "123123";//Not Recorded 
     //} 

Bu kod <testTag.01>SomeValue</testTag.01> veya <testTag.01 xsi:nil="true"/> üretir. Ben BAŞKA yorumsuz

, sonuç şöyle olacaktır: <testTag.01>SomeValue</testTag.01> veya <testTag.01 NV="123123" />.

Yani nasıl doğrulama aracı tarafından gerekli biçime almak için hiçbir fikrim yok. Herhangi bir fikir ?

P.S. Burada

otomatik oluşturulan C# sınıfıdır:

/// [System.CodeDom.Compiler.GeneratedCodeAttribute ("XSD", "4.0.30319.33440")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute ("kod")] [System.Xml.Serialization.XmlTypeAttribute (AnonymousType = doğru mu, Ad = "http://www.blabla.org ")]

halka kısmi sınıf testTag01 {

private string nvField; 

private SomeEnum valueField; 

/// <remarks/> 
[System.Xml.Serialization.XmlAttributeAttribute()] 
public string NV { 
    get { 
     return this.nvField; 
    } 
    set { 
     this.nvField = value; 
    } 
} 

/// <remarks/> 
[System.Xml.Serialization.XmlTextAttribute()] 
public SomeEnum Value { 
    get { 
     return this.valueField; 
    } 
    set { 
     this.valueField = value; 
    } 
} } 

O bölümü değiştirmek istemez, ama bunu yapmadan imkansızdır anlıyoruz. Ayrıca, SomeEnum'u Nullable olarak ayarlamaya çalıştım. public SomeEnum? Value, ancak bir istisna atıyor:

Cannot serialize member 'Value' of type System.Nullable`1[]. XmlAttribute/XmlText cannot be used to encode complex types. 
+0

Otomatik oluşturulan sınıfları görmeniz gerekir. Bunların genellikle düzenlenmesi gerekiyordu. Boş değerleri üretmek için kod eklemeniz gerekmemelidir. – jdweng

+0

Dersi verdim. Ayrıca Değeri Null olarak ayarlamayı denedim, ancak bir istisna atıyor. :-( – Tech0

+1

Bu kutudan çıkmayacak. Bkz. [** Xsi: nil Öznitelik Bağlama Desteği **: nil niteliği ve diğer özellikler] (https://msdn.microsoft.com/en-us/library/ ybce7f69.aspx) – dbc

cevap

1

XmlSerializer direkt olarak aynı anda başka özellik değerleri ile birlikte xsi:nil="true" sahip elemanlarına bağlanarak desteklememektedir; Xsi:nil Attribute Binding Support: The nil attribute and other attributes'a bakın.

Böylece, el niteliğini yayarlar gerekir.

hiçbir içerik ve iki özelliklere sahip bir eleman oluşturmak mümkün olmasını istiyorsanız

bir NV adlandırılır ve diğer hep xsi:nil="true" olmanın, bir sentetik özelliği yanı sıra NV özelliği bulunması için testTag01 sınıfını değiştirebilir Eğer bazen xsi:nil="true" olması ama diğer zamanlarda istediğiniz en öğesi SomeEnum tekabül içeriğe sahip olmak istiyorsanız

public class testTag01 
{ 
    [XmlAttribute] 
    public string NV { get; set; } 

    [XmlAttribute("nil", Namespace = "http://www.w3.org/2001/XMLSchema-instance")] 
    public string Nil { get { return "true"; } set { } } 
} 

, senin bir işi bir bi yapmanız gerekir: doğru ad ve ad sahip T daha karmaşık, xsi:nil="true" element içeriğine sahip olduğunda bastırılması gerektiğinden: aynı anda XML standard ihlali olur hem xsi:nil="true" ve içeriğine sahip

public class testTag01 
{ 
    [XmlAttribute] 
    public string NV { get; set; } 

    [XmlAttribute("nil", Namespace = "http://www.w3.org/2001/XMLSchema-instance")] 
    public string Nil { get { return SomeEnum == null ? "true" : null; } set { } } 

    public bool ShouldSerializeNil() { return SomeEnum == null; } 

    [XmlIgnore] 
    public SomeEnum? SomeEnum { get; set; } 

    [XmlText] 
    public string SomeEnumText 
    { 
     get 
     { 
      if (SomeEnum == null) 
       return null; 
      return SomeEnum.Value.ToString(); 
     } 
     set 
     { 
      // See here if one needs to parse XmlEnumAttribute attributes 
      // http://stackoverflow.com/questions/3047125/retrieve-enum-value-based-on-xmlenumattribute-name-value 
      value = value.Trim(); 
      if (string.IsNullOrEmpty(value)) 
       SomeEnum = null; 
      else 
      { 
       try 
       { 
        SomeEnum = (SomeEnum)Enum.Parse(typeof(SomeEnum), value, false); 
       } 
       catch (Exception) 
       { 
        SomeEnum = (SomeEnum)Enum.Parse(typeof(SomeEnum), value, true); 
       } 
      } 
     } 
    } 
} 

(bir eleman; umarım bunu yok)

Sonra gibi kullanın:.

<TestClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <testTag.01 NV="123123" xsi:nil="true" /> 
</TestClass> 

Ya

<TestClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <testTag.01 NV="123123">SomeValue</testTag.01> 
</TestClass> 
:

public class TestClass 
{ 
    [XmlElement("testTag.01")] 
    public testTag01 TestTag { get; set; } 

    public static void Test() 
    { 
     Test(new TestClass { TestTag = new testTag01 { NV = "123123" } }); 
     Test(new TestClass { TestTag = new testTag01 { NV = "123123", SomeEnum = SomeEnum.SomeValue } }); 
    } 

    private static void Test(TestClass test) 
    { 
     var xml = test.GetXml(); 

     var test2 = xml.LoadFromXML<TestClass>(); 

     Console.WriteLine(test2.GetXml()); 
     Debug.WriteLine(test2.GetXml()); 

     if (test2.TestTag.NV != test.TestTag.NV) 
     { 
      throw new InvalidOperationException("test2.TestTag.NV != test.TestTag.NV"); 
     } 
    } 
} 

XML çıktı benziyor

Prototip fiddle kullanarak bu uzatma yöntemleri: kutunun dışında bu durum için herhangi bir çözüm yoktur beklenen, bu yüzden biraz doğaçlama ve bir post işleme mantığında Amacım elde gibi

public static class XmlSerializationHelper 
{ 
    public static T LoadFromXML<T>(this string xmlString, XmlSerializer serializer = null) 
    { 
     T returnValue = default(T); 

     using (StringReader reader = new StringReader(xmlString)) 
     { 
      object result = (serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader); 
      if (result is T) 
      { 
       returnValue = (T)result; 
      } 
     } 
     return returnValue; 
    } 

    public static string GetXml<T>(this T obj, XmlSerializerNamespaces ns = null, XmlWriterSettings settings = null, XmlSerializer serializer = null) 
    { 
     using (var textWriter = new StringWriter()) 
     { 
      settings = settings ?? new XmlWriterSettings() { Indent = true, IndentChars = " " }; // For cosmetic purposes. 
      using (var xmlWriter = XmlWriter.Create(textWriter, settings)) 
       (serializer ?? new XmlSerializer(typeof(T))).Serialize(xmlWriter, obj, ns); 
      return textWriter.ToString(); 
     } 
    } 
} 
0

.

Oluşturulan XML'yi ayrıştırıyorum ve xsi: nil özniteliğine sahip, ancak NV özniteliği olmayan bir düğüm arıyorsam - Ben, NV özniteliğini varsayılan değer ile ekliyorum. NV özniteliğine sahip düğümler için aynıdır, ancak xsi: nil olmaz. İşte

kodudur:

 XmlDocument doc = new XmlDocument();// instantiate XmlDocument and load XML from file 
     doc.Load("somepath.xml"); 

     //Get the nodes with NV attribute(using XPath) and add xsi:nill to that nodes 
     XmlNodeList nodes = doc.SelectNodes("//*[@NV]"); 

     foreach (XmlNode node in nodes) 
     { 
      XmlAttribute nilAttr = doc.CreateAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"); 
      nilAttr.Value = "true"; 
      node.Attributes.Append(nilAttr); 
     } 

     //Get the nodes with xsi:nill attribute(using XPath) and add NV with default value to that nodes 
     XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable); 
     nsManager.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); 
     XmlNodeList nilNodes = doc.SelectNodes("//*[@xsi:nil]", nsManager); 

     foreach (XmlNode node in nilNodes) 
     { 
      XmlAttribute nvAttr = doc.CreateAttribute("NV"); 
      nvAttr.Value = "7701003"; 
      node.Attributes.Append(nvAttr); 
     } 

     doc.Save("somepath.xml"); 

üst cevabı tamamen mantıklı ama bu sınıflar otomatik olarak oluşturulduğunu beri, o sonrası işleme ile yolumu yapmak sağlayıcıya eğer neden olacaktır XSD şemasını değiştirir, çözümüm ekstra çalışmaya gerek duymaz. Yine de teşekkürler.

+1

Aslında, framework sürümlerine bağlı olarak, Oluşturulan sınıfı bir kısmi olarak yayınlayabilmek için, "her zaman sıfır özniteliğini" yukarıdaki yerine ikinci bir sınıf dosyasına ekleyebilirsiniz. –

İlgili konular