2013-12-18 157 views
2

我需要生成序列化過程中的下列XML: (片段)XML屬性沒有得到命名空間前綴

<IncidentEvent a:EventTypeText="Beginning" xmlns:a="http://foo"> 
    <EventDate>2013-12-18</EventDate> 
    <EventTime>00:15:28</EventTime> 
</IncidentEvent> 

有問題的類看起來是這樣的:

public class IncidentEvent 
{ 
    public string EventDate { get; set; } 
    public string EventTime { get; set; } 

    [XmlAttribute("EventTypeText", Namespace = "http://foo")] 
    public string EventTypeText { get; set; } 

} 

看來,串行注意到名稱空間已經在xmlns中聲明:在根目錄下,並且忽略了我的屬性。我也試過如下:

[XmlRoot(Namespace = "http://foo")] 
public class IncidentEvent 
{ 
    public string EventDate { get; set; } 
    public string EventTime { get; set; } 

    private XmlSerializerNamespaces _Xmlns; 

    [XmlNamespaceDeclarations] 
    public XmlSerializerNamespaces Xmlns 
    { 
     get 
     { 
      if (_Xmlns == null) 
      { 
       _Xmlns = new XmlSerializerNamespaces(); 
       _Xmlns.Add("ett", "http://foo"); 
      } 

      return _Xmlns; 
     } 

     set 
     { 
      _Xmlns = value; 
     } 
    } 


    [XmlAttribute("EventTypeText", Namespace = "http://foo")] 
    public string EventTypeText { get; set; } 

} 

這將導致以下XML:

<ett:IncidentEvent EventTypeText="Beginning" xmlns:ett="http://foo"> 
    <ett:EventDate>2013-12-18</ett:EventDate> 
    <ett:EventTime>00:15:28</ett:EventTime> 
    </ett:IncidentEvent> 

這是不是我想要的。該元素不應該加前綴,該屬性應該是。需要什麼來讓序列化程序理解我想要的?

回答

0

我做了一些研究,可以以下的答案有助於

的屬性有空間前綴你必須指定一個不同於你指定的名稱空間標籤http://foo。以下代碼希望能夠解決您的問題。在代碼中,我刪除了元素的名稱空間並僅添加了屬性。

public class IncidentEvent 
{ 
    public string EventDate { get; set; } 
    public string EventTime { get; set; } 

    [XmlAttribute("EventTypeText", Namespace = "http://foo")] 
    public string EventTypeText { get; set; } 

} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IncidentEvent xmlObj = new IncidentEvent() 
     { 
      EventDate = "2012.12.01", 
      EventTime = "1:00:00", 
      EventTypeText = "Beginining" 
     }; 
     XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
     ns.Add("ett", "http://foo"); 
     XmlSerializer serializer = new XmlSerializer(typeof(IncidentEvent)); 
     serializer.Serialize(Console.OpenStandardOutput(), xmlObj, ns); 
     Console.WriteLine(); 
    } 
} 

http://www.w3.org/TR/2009/REC-xml-names-20091208/#defaulting

+0

如果需要將此對象序列化爲另一個對象的子對象,這似乎會分崩離析。當我在一個場景中測試它時它運行良好,但我忘記了另一個場景。仍然,很好的答案。 – kettch

0

命名空間是爲了區分具有相同名稱的兩個XML元素。由於不同的XML元素可以具有相同的屬性名稱,但含義不同。因此,對屬性使用名稱空間標記沒有任何優勢,因爲XML屬性僅被視爲「元素名稱空間」的一部分。 在您的例子

<ett:IncidentEvent EventTypeText="Beginning" xmlns:ett="http://foo"> 
    <ett:EventDate>2013-12-18</ett:EventDate> 
    <ett:EventTime>00:15:28</ett:EventTime> 
</ett:IncidentEvent> 

EventTypeText是命名空間ETT的一部分:IncidentEvent 請參考http://www.w3.org/TR/REC-xml-names/爲XML命名空間

+0

XML需要根據我無法控制的XSD進行驗證。我所需要做的就是編寫符合模式的XML。我的第一個片段是手寫的,但它確實有效。我只需要弄清楚如何讓序列化器執行相同的操作。 – kettch

0

我給KKD信貸的答案,但我發現了另一個場景,還是會造成一些問題。顯然,如果要序列化的對象是另一個對象的子對象,如果父對象的名稱空間與子對象的名稱空間相同,則序列化程序假定您不需要顯式聲明該子對象的名稱空間。

public class IncidentEvent : IXmlSerializable 
{ 
    public string EventDate { get; set; } 
    public string EventTime { get; set; } 
    public string EventTypeText { get; set; } 

    public System.Xml.Schema.XmlSchema GetSchema() 
    { 
     return null; 
    } 

    public void ReadXml(System.Xml.XmlReader reader) 
    { 
     return null; 
    } 

    public void WriteXml(System.Xml.XmlWriter writer) 
    { 
     writer.WriteAttributeString("ex", "EventTypeText", "http://foo", EventTypeText); 
    } 
} 

通過實現IXmlSerializable,我可以以我需要的方式手動寫出元素和屬性。由於這是單向導出,因此我不需要執行WriteXml方法。

我還不確定這是不是最好的方式,但它的工作。

3

這可能是XmlSerializer中的一個錯誤。

正如您已經注意到的,即使當明確設置XmlAttributeAttribute.Namespace時,該屬性在某些情況下也不會作爲前綴。從測試來看,這似乎在屬性名稱空間恰好與當前正在寫入的元素的名稱空間相同時發生。

例如:

[XmlRoot(Namespace = "http://foo")] 
public class IncidentEvent 
{ 
    [XmlAttribute("EventTypeText", Namespace = "http://foo")] 
    public string EventTypeText { get; set; } 
} 

序列化下面的XML:

<q1:IncidentEvent EventTypeText="an attribute" xmlns:q1="http://foo" /> 

而且由於屬性前綴的,它實際上沒有任何名稱空間,如解釋in the XML standard無前綴屬性名稱的名稱空間名稱始終沒有值

但是,下面的:

[XmlRoot(Namespace = "http://foo")] 
public class IncidentEvent 
{ 
    [XmlAttribute("EventTypeText", Namespace = "http://bar")] 
    public string EventTypeText { get; set; } 
} 

序列化與正確前綴屬性:

<q1:IncidentEvent p1:EventTypeText="an attribute" xmlns:p1="http://bar" xmlns:q1="http://foo" /> 

解決方法是明確設置[XmlAttribute(Form = XmlSchemaForm.Qualified)]。因此:根據需要

[XmlRoot(Namespace = "http://foo")] 
public class IncidentEvent 
{ 
    [XmlAttribute("EventTypeText", Namespace = "http://foo", Form = XmlSchemaForm.Qualified)] 
    public string EventTypeText { get; set; } 
} 

序列化到

<q1:IncidentEvent q1:EventTypeText="an attribute" xmlns:q1="http://foo" /> 

相關問題