如何在ASP.NET WebAPI中使用元素前缀反序列化XML?

时间:2017-03-20 10:17:59

标签: c# xml asp.net-web-api xml-deserialization

我遇到了一个恼人的问题,我试图为我的一个控制器反序列化一个XML有效负载,但是有效负载可能没有命名空间或者在所有元素上都有命名空间前缀。

我尝试使用Namespace = ""将XML属性添加到我的模型中,试图让模型无关紧要,但这不起作用。我也尝试将我的XmlSerialiser上的默认命名空间设置为"",但这没有帮助。我也尝试了[XmlNamespaceDeclarations]属性并没有运气。

以下是我可以收到的两个不同有效载荷的示例,以防我在说明中不清楚。

<ex:root namespace:ex="http://example.com/ns"> <ex:element>Example</ex:element> <ex:secondElement>Example2</ex:secondElement> </ex:root>

<root> <element>Example</element> <secondElement>Example</secondElement> </root>

以下是我将尝试反序列化到

的有效负载的模型
[XmlRoot("root")]
public class Root
{
   [XmlElement("element")]
   public string Element {get; set;}

   [XmlElement("secondElement")]
   public string SecondElement {get; set;}
}

如果在其他地方得到解答,我真诚地道歉,但我已经尝试了解决我能找到的与我的问题相关的每个问题的解决方案,并且没有成功。

提前谢谢。

编辑:修复了命名空间的XML示例

2 个答案:

答案 0 :(得分:1)

不确定你是如何尝试反序列化的,但是这样的事情会起作用:

var xml = File.ReadAllText("sample.xml");
var serializer = new XmlSerializer(typeof(Root));
var obj = serializer.Deserialize(new StringReader(xml));

答案 1 :(得分:0)

由于可能首先出现在根中的两个不同的可能元素,我们需要表达该选择(并且类似于第二个元素)。我试图直接编写正确的代码但是失败了,所以我首先编写了一个表示需要的模式,然后使用xsd command line tool生成C#代码 1 。 / p>

首先,主要架构:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:ex="http://example.com/ns" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:import namespace="http://example.com/ns" />
    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:choice>
                    <xs:element ref="ex:element" />
                    <xs:element name="element" >
                    </xs:element>
                </xs:choice>
                <xs:choice>
                    <xs:element ref="ex:secondElement"  />
                    <xs:element name="secondElement" />
                </xs:choice>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

然后我们需要另一个模式来描述ns模式:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="XMLSchema1"
    targetNamespace="http://example.com/ns"
    elementFormDefault="qualified"
    xmlns="http://example.com/ns"
    xmlns:mstns="http://example.com/ns"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
    <xs:element name="element"/>
    <xs:element name="secondElement"/>
</xs:schema>

然后我们运行xsd /classes XmlFile1.xsd XMLSchema1.xsd(假设给出了两个xsd文件的名称。

这会吐出一个类:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.Xml.Serialization;

// 
// This source code was auto-generated by xsd, Version=4.6.1055.0.
// 


/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class root {

    private object itemField;

    private ItemChoiceType itemElementNameField;

    private object item1Field;

    private Item1ChoiceType item1ElementNameField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("element", typeof(object))]
    [System.Xml.Serialization.XmlElementAttribute("element", typeof(object), Namespace="http://example.com/ns")]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")]
    public object Item {
        get {
            return this.itemField;
        }
        set {
            this.itemField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public ItemChoiceType ItemElementName {
        get {
            return this.itemElementNameField;
        }
        set {
            this.itemElementNameField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("secondElement", typeof(object), Namespace="http://example.com/ns")]
    [System.Xml.Serialization.XmlElementAttribute("secondElement", typeof(object))]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("Item1ElementName")]
    public object Item1 {
        get {
            return this.item1Field;
        }
        set {
            this.item1Field = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public Item1ChoiceType Item1ElementName {
        get {
            return this.item1ElementNameField;
        }
        set {
            this.item1ElementNameField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(IncludeInSchema=false)]
public enum ItemChoiceType {

    /// <remarks/>
    element,

    /// <remarks/>
    [System.Xml.Serialization.XmlEnumAttribute("http://example.com/ns:element")]
    element1,
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(IncludeInSchema=false)]
public enum Item1ChoiceType {

    /// <remarks/>
    [System.Xml.Serialization.XmlEnumAttribute("http://example.com/ns:secondElement")]
    secondElement,

    /// <remarks/>
    [System.Xml.Serialization.XmlEnumAttribute("secondElement")]
    secondElement1,
}

您可以编辑/调整以满足您的确切需求。例如。我不认为此处使用的类型(object)非常理想,可能会调整为string

这就是我简化为:

using System.Xml.Serialization;

[System.Serializable()]
[XmlType(AnonymousType = true)]
[XmlRoot("root", Namespace = "", IsNullable = false)]
public partial class Root
{

    [XmlElement("element", typeof(string))]
    [XmlElement("element", typeof(string), Namespace = "http://example.com/ns")]
    [XmlChoiceIdentifier("ElementType")]
    public string Element { get; set; }

    [XmlIgnore()]
    public ElementType ElementType { get; set; }

    [XmlElement("secondElement", typeof(string), Namespace = "http://example.com/ns")]
    [XmlElement("secondElement", typeof(string))]
    [XmlChoiceIdentifier("SecondElementType")]
    public string SecondElement { get; set; }

    [XmlIgnore()]
    public SecondElementType SecondElementType { get; set; }
}

/// <remarks/>
[System.Serializable()]
[XmlType(IncludeInSchema = false)]
public enum ElementType
{
    element,
    [XmlEnum("http://example.com/ns:element")]
    nsElement,
}

/// <remarks/>
[System.Serializable()]
[XmlType(IncludeInSchema = false)]
public enum SecondElementType
{
    secondElement,
    [XmlEnum("http://example.com/ns:secondElement")]
    nsSecondElement,
}

1 如果您有实际提供的xsd来描述XML,那么我建议使用它而不是从头开始编写新的XML。我提供的那个实际上是能够成功运行xsd的最小值。不知怎的,我对此表示怀疑,因为这看起来更像是由不了解XML,名称空间,模式等的人生成的。