4

例如,如何在 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 声明而苦苦挣扎。有任何想法吗?

4

5 回答 5

2

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

[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>
于 2013-02-21T00:49:19.000 回答
1

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

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 对象(现代/LINQ 方式为XDocument ,如果您更喜欢 DOM,则为XmlDocument)可能是更简单的方法。

于 2013-02-21T16:46:25.543 回答
0

尝试使用 .NET 4.0+ 的程序集 System.Xaml 中的 XAML 序列化程序。

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

于 2013-02-21T00:52:41.537 回答
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);
}

再次感谢大家的共同努力。我自己不会得到这个!

于 2013-02-21T19:56:52.083 回答
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);

如果您提供一个随机 url 而不是"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> StartElement 需要writer.WriteStartElement("test1", ns1);在需要时关闭writer.WriteEndElement();

于 2018-04-13T12:29:56.353 回答