如何在C#中创建具有多个命名空间属性的XML

时间:2013-02-20 23:35:12

标签: c# .net xml serialization

如何在C#

中生成此XML
<?xml version='1.0'?>
<oneshot xmlns='http://www.w3.org/2002/xforms' xmlns:dm='http://mobileforms.foo.com/xforms' xmlns:h='http://www.w3.org/1999/xhtml' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
  <dm:form_namespace>Foo</dm:form_namespace>
  <Days>6</Days>
  <Leave_Type>Option 3</Leave_Type>
</oneshot>

我特意挣扎于xmlns:dm声明。有什么想法吗?

5 个答案:

答案 0 :(得分:2)

你最好的选择(阅读:最少量的黑客攻击)可能是一个自定义IXmlSerializable实现;你可以通过XmlRootAttributeXmlElementAttribute等的组合获得你想要的 part-way ,如下所示:

[Serializable]
[XmlRoot("oneshot")]
public class OneShot 
{
    [XmlElement("form_namespace", Namespace="http://mobileforms.foo.com/xforms")]
    public string FormNamespace {get; set;}
    [XmlElement("Days")]
    public int Days {get; set;}
    [XmlElement("Leave_Type")]
    public string LeaveType {get; set;}

这将生成如下内容:

<?xml version="1.0" encoding="utf-16"?>
<oneshot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <form_namespace xmlns="http://mobileforms.foo.com/xforms">Foo</form_namespace>
  <Days>6</Days>
  <Leave_Type>Option 3</Leave_Type>
</oneshot>

但如果您实施IXmlSerializable,则可以完全控制:

public class OneShot : IXmlSerializable
{
    public string FormNamespace {get; set;}
    public int Days {get; set;}
    public string LeaveType {get; set;}

    #region IXmlSerializable
    public void WriteXml (XmlWriter writer)
    {
        writer.WriteStartElement("oneshot");
        writer.WriteAttributeString("xmlns", null, "http://www.w3.org/2002/xforms");
        writer.WriteAttributeString("xmlns:dm", null, "http://mobileforms.foo.com/xforms");
        writer.WriteAttributeString("xmlns:h", null, "http://www.w3.org/1999/xhtml");
        writer.WriteAttributeString("xmlns:xsd", null, "http://www.w3.org/2001/XMLSchema");
        writer.WriteElementString("dm:form_namespace", null, FormNamespace);
        writer.WriteElementString("Days", Days.ToString());
        writer.WriteElementString("Leave_Type", LeaveType);
        writer.WriteEndElement();
    }

    public void ReadXml (XmlReader reader)
    {
        // populate from xml blob
    }

    public XmlSchema GetSchema()
    {
        return(null);
    }
    #endregion
}

这给了你:

<?xml version="1.0" encoding="utf-16"?>
<OneShot>
  <oneshot xmlns="http://www.w3.org/2002/xforms" xmlns:dm="http://mobileforms.foo.com/xforms" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <dm:form_namespace>Foo</dm:form_namespace>
    <Days>6</Days>
    <Leave_Type>Option 3</Leave_Type>
  </oneshot>
</OneShot>

答案 1 :(得分:1)

使用不同命名空间中的节点编写XML的一种方法是使用XmlWriter.WriteElementString的4参数版本以您希望的方式显式指定命名空间和前缀:

var s = new StringWriter();
using (var writer = XmlWriter.Create(s))
{
    writer.WriteStartElement("oneshot", "http://www.w3.org/2002/xforms");
    writer.WriteElementString("dm", "form_namespace", 
         "http://mobileforms.foo.com/xforms","Foo");
    // pick "http://www.w3.org/2002/xforms" by default for Days node
    writer.WriteElementString("Days", "6");
    // or you can explicitly specify "http://www.w3.org/2002/xforms"
    writer.WriteElementString("Leave_Type", 
         "http://www.w3.org/2002/xforms", "Option 3");
    writer.WriteEndElement();
}

Console.Write(s.ToString());

请注意,您的示例XML定义的前缀多于XML中使用的前缀。如果您的要求是生成“文本相同的XML”(从XML的角度来看相同,但没有必要用相同的文本表示),您可能需要花费更多精力在您需要的位置添加名称空间前缀和xmlns属性。

注意2:首先创建XML对象(XDocument用于现代/ LINQ方式,或XmlDocument如果你更喜欢DOM)可能更容易。

答案 2 :(得分:0)

尝试使用.NET 4.0 +程序集System.Xaml。

中的XAML序列化程序

您可能需要添加属性以将属性标记为内容而不是XML属性。

答案 3 :(得分:0)

谢谢,大家,求助!这是上述两个答案的组合,它为我做了。我将设置一个提出IXmlSerializable方法的方法,因为这是解决方案的主要部分。

我必须在类名上声明XMLRoot标记,删除WriteStartElement和WriteEndElement,然后使用四参数声明。

这是最终有效的课程:

[Serializable]
[XmlRoot("oneshot")]
public class LeaveRequestPush : IXmlSerializable
{
    public string FormNamespace { get; set; }
    public int Days { get; set; }
    public string LeaveType { get; set; }

    #region IXmlSerializable

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteElementString("dm", "form_namespace", "http://mobileforms.devicemagic.com/xforms", FormNamespace);
        writer.WriteElementString("Days", Days.ToString());
        writer.WriteElementString("Leave_Type", LeaveType);
    }
}

public void ReadXml (XmlReader reader)
{
    // populate from xml blob
}

public XmlSchema GetSchema()
{
    return(null);
}

再次感谢所有人的共同努力。我不会自己拿这个!

答案 4 :(得分:0)

这段代码可以解决问题!

public void WriteXml(XmlWriter writer)
        {
            const string ns1 = "http://firstline.com/";
            const string xsi = "http://www.w3.org/2001/XMLSchema-instance";
            writer.WriteStartElement("myRoot", ns1);
            writer.WriteAttributeString("SchemaVersion", "1.0");
            writer.WriteAttributeString("xmlns", "xsi", "http://www.w3.org/2000/xmlns/", xsi);
            writer.WriteAttributeString("xsi", "schemaLocation", xsi, ns1 + " schema1.xs");

        writer.WriteStartElement("element1", ns1);
        writer.WriteElementString("test1", ns1, "test value");
        writer.WriteElementString("test2", ns1, "value 2");
        writer.WriteEndElement();
        writer.WriteEndElement();//to close classname that has root xml
}

具有多个令人敬畏的命名空间的Xml!

<?xml version="1.0" encoding="utf-16"?>
<myClassNameWhereIXmlSerializableIsImplemented>
  <myRoot SchemaVersion="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://firstline.com/ schema1.xs" xmlns="http://firstline.com/">
    <element1>
      <test1>test value</test1>
      <test2>value 2</test2>
    </element1>
  </myRoot>
</myClassNameWhereIXmlSerializableIsImplemented>

这条线有点令人困惑

writer.WriteAttributeString("xmlns", "xsi", "http://www.w3.org/2000/xmlns/", xsi);

如果您提供随机网址而不是"http://www.w3.org/2000/xmlns/",则会失败。 xml中出现的url实际上来自“xsi”变量。 再举一个证明这一点的例子

writer.WriteAttributeString("xml", "base", "http://www.w3.org/XML/1998/namespace", base1);

其中base1 = "<custom url>"

如果你想输出一个像<d:test1>somevalue<\d:test1>这样的前缀,那么writer.WriteElementString("d","test1", ns1, "somevalue");如果上面没有定义ns1,那么它将被添加到xml输出中。

但是 <d:test1> <blah>... <\d:test1> 需要writer.WriteStartElement("test1", ns1);时需要使用writer.WriteEndElement();

关闭StartElement