C# XSD转换为XML。多个没有前缀的名称空间。如何?
我使用XSD文件通过XSD.exe生成C#代码,并使用生成的代码序列化XML 问题是,我必须生成一个具有defat/root xmlns名称空间的XML文件,以及一个在此元素上定义另一个“原始”名称空间的元素(不带前缀) 以下是一个简单的示例(不是整个XML),用于说明:C# XSD转换为XML。多个没有前缀的名称空间。如何?,c#,xml,xsd,xml-serialization,xml-namespaces,C#,Xml,Xsd,Xml Serialization,Xml Namespaces,我使用XSD文件通过XSD.exe生成C#代码,并使用生成的代码序列化XML 问题是,我必须生成一个具有defat/root xmlns名称空间的XML文件,以及一个在此元素上定义另一个“原始”名称空间的元素(不带前缀) 以下是一个简单的示例(不是整个XML),用于说明: <?xml version="1.0" encoding="utf-16"?> <Request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" x
<?xml version="1.0" encoding="utf-16"?>
<Request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://mynamespace">
<ABC>STACKOVERFLOW</ABC>
<Method Name="TEST" xmlns="http://myothernamespace">
<DEF>123456</DEF>
</Method>
</Request>
堆栈溢出
123456
我找不到在Method元素(没有前缀)上“插入”第二个xmlns属性的方法
问题是我不能使用前缀,因为这个XML被发送到另一端没有使用XML反序列化器的应用程序,但它正在将XML解析为字符串并寻找精确的字符串匹配(当然,这不可能更改这个“接收”应用程序) 我在XSD中尝试了很多不同的方法,但都不起作用:(我使用MSMQ传输XML消息,所以我不是自己序列化请求(只是给请求对象提供正确的参数,序列化在幕后处理) 我可以使用XmlSerializer将XML序列化为一个字符串,而不使用第二个xmlns,并在发送之前通过编码将其添加到XML(到字符串),但这是肮脏的,让我无法这样做,只在方法元素上添加这个“xmlns”属性 有没有办法通过纯XSD(通过使用XSD.exe生成.NET代码)来解决这个问题 希望我的问题很清楚,希望有人能回答
提前感谢!不,如果您将http://myothernamespace“>对于根节点,所有未固定的节点都将被视为该名称空间中的节点。上述格式称为默认名称空间。您确实需要添加更多的代码才能在Xpath中使用它 e、 g 在您的示例中,
SomeNode。选择SingleNode(“测试”)
将不起作用
您需要手动将命名空间添加到NameSpaceManager的实例中,并使用占用管理器的重载
e、 g
及
它们是不同的动物
为了使其正确序列化,您可以使用XmlSerialiserNamespaces实例将其添加为前缀“”,然后将其传递给serialiser
这里的上一个问题是在VB.Net中,但是你会明白的
像这样定义您的类型:
[XmlRoot("Method")]
public class MyMethod
{
[XmlAttribute]
public String Name { get; set; }
[XmlElement]
public int DEF { get; set; }
}
[XmlRoot("Request", Namespace="http://mynamespace")]
public class MyRequest
{
[XmlElement]
public String ABC { get; set; }
[XmlElement(Namespace="http://myothernamespace")]
public MyMethod Method { get; set; }
}
支持代码:
static TextWriter GetWriter(bool wantSave)
{
if (wantSave)
{
var fs = new FileStream(StorageFile, FileMode.Create);
return new StreamWriter(fs, new UTF8Encoding());
}
return Console.Out;
}
private static void ShoworSave(MyRequest r, bool wantSave)
{
if (r==null)
{
Console.WriteLine(" --null--");
return;
}
Console.WriteLine("\n");
var writerSettings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true
};
using (XmlWriter xmlWriter =
XmlWriter.Create(GetWriter(wantSave), writerSettings))
{
XmlSerializer ser = new XmlSerializer(r.GetType());
var ns = new XmlSerializerNamespaces();
ns.Add("", "http://mynamespace"); // default xmlns
ser.Serialize(xmlWriter, r, ns);
}
Console.WriteLine("\n");
}
然后像这样使用:
var request = new MyRequest
{
ABC = "HelloWorld",
Method = new MyMethod
{
Name="TEST",
DEF=123456
}
};
SaveOrShow(request, false);
结果:
<Request xmlns="http://mynamespace">
<ABC>HelloWorld</ABC>
<Method Name="TEST" xmlns="http://myothernamespace">
<DEF>123456</DEF>
</Method>
</Request>
你好世界
123456
讨论
Xml序列化程序允许您指定命名空间映射,通过该映射,您可以为序列化输出提供命名空间前缀列表及其映射到的实际命名空间。若要设置默认Xml命名空间及其前缀,请使用前缀“”(空字符串)
因此,我使用的代码指定了默认名称空间
我还使用适当的xml序列化程序属性修饰了各种类型和成员,以获得正确的名称空间
乍一看,您可能认为xml名称空间字符串的使用(在您的示例中)http://mynamespace)在代码中几个不同的地方违反了“不要重复你自己”干净编码的格言。但这不是真的。在我使用它的一个地方,它设置类型的XML命名空间。在另一个地方,它指定序列化程序的默认XML命名空间
如果我没有指定后者,那么您将得到一个前缀;这将为您提供语义上等价的xml信息集,但是因为您说您的接收方应用程序不是真正的xml感知应用程序,所以它将破坏该接收方
同样,关于XSD.EXE和代码生成的问题,不确定你在做什么,但是考虑一下:Xsd.exe只是一个工具。使用这个工具的输出并调整它,编辑它没有什么不对。如果你的类型相对简单,你可能会发现更简单地定义C中的类型,如我上面所示。如果您大量使用XSD作为源代码,那么您将需要依赖XSD.exe工具。在这种情况下,您需要在XSD文档中的适当位置指定这些名称空间。您可以选择哪个选项。
您是如何生成XSD和类的?请保存一份XML副本,然后尝试XSD.exe/d request.XML
后跟>xsd.exe/l:cs/c request.xsd request_app1.xsd
“另一端未使用XML反序列化程序,但正在将XML解析为字符串的应用程序”-我们为什么容忍在我们的职业中有这样的人?如果他们是医生,他们将被从登记册上除名,并因其不称职而被起诉。非常感谢你在我的问题上投入的时间&你提出的详细解决方案!非常清楚,有趣,这项工作做得好,但我的问题是“更高”一级由于我自己不生成类型,而是让XSD.exe从XSD文件中完成工作(因此我的问题更多:如何编写XSD,以便XSD.exe生成您手动编写的C#类型),实际上JamieSee的简短评论(从XML生成XSD)在这方面也帮了我很大的忙,有了你的回答,我现在对事情有了更好的理解,我将能够解决我的问题!再次感谢!
var request = new MyRequest
{
ABC = "HelloWorld",
Method = new MyMethod
{
Name="TEST",
DEF=123456
}
};
SaveOrShow(request, false);
<Request xmlns="http://mynamespace">
<ABC>HelloWorld</ABC>
<Method Name="TEST" xmlns="http://myothernamespace">
<DEF>123456</DEF>
</Method>
</Request>