XML 解析器缺少名称空间
XML namespace missing for parser
我必须解析缺少 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 命名空间的 XML,因此 xml 看起来像这样:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<program>
<scriptList>
<script type="StartScript">
<isUserScript>false</isUserScript>
</script>
</scriptList>
</program>
但应该是这样的:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<program xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<scriptList>
<script xsi:type="StartScript">
<isUserScript>false</isUserScript>
</script>
</scriptList>
</program>
类型属性确保正确的子类,例如
class StartScript : script
{...}
解析器是通过 $> xsd.exe a.xsd /类 (.Net) 从手写 xsd 自动生成的。
这是 xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="qualified">
<!-- Main element -->
<xs:element name="program">
<xs:complexType>
<xs:sequence>
<xs:element name="scriptList">
<xs:complexType>
<xs:sequence>
<xs:element name="script" type="script" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="script" />
<xs:complexType name="StartScript">
<xs:complexContent>
<xs:extension base="script">
<xs:all>
<xs:element name="isUserScript" type="xs:boolean"></xs:element>
</xs:all>
</xs:extension>
</xs:complexContent>
</xs:complexType>
一个简单的解决方案是 运行 在输入 XML 上进行字符串替换(“type=\”“到”xsi:type=\“”),但这很漂亮丑陋的。
有更好的解决方案吗?
您可以将 XML 加载到中间 LINQ to XML XDocument
中,修复 <script>
元素上的属性命名空间,然后直接反序列化为最终的 class:
// Load to intermediate XDocument
XDocument xDoc;
using (var reader = XmlReader.Create(f))
xDoc = XDocument.Load(reader);
// Fix namespace of "type" attributes
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
foreach (var element in xDoc.Descendants("script"))
{
var attr = element.Attribute("type");
if (attr == null)
continue;
var newAttr = new XAttribute(xsi + attr.Name.LocalName, attr.Value);
attr.Remove();
element.Add(newAttr);
}
// Deserialize directly to final class.
var program = xDoc.Deserialize<program>();
使用扩展方法:
public static class XObjectExtensions
{
public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null)
{
if (element == null)
throw new ArgumentNullException();
using (var reader = element.CreateReader())
return (T)(serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader);
}
}
我必须解析缺少 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 命名空间的 XML,因此 xml 看起来像这样:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<program>
<scriptList>
<script type="StartScript">
<isUserScript>false</isUserScript>
</script>
</scriptList>
</program>
但应该是这样的:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<program xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<scriptList>
<script xsi:type="StartScript">
<isUserScript>false</isUserScript>
</script>
</scriptList>
</program>
类型属性确保正确的子类,例如
class StartScript : script
{...}
解析器是通过 $> xsd.exe a.xsd /类 (.Net) 从手写 xsd 自动生成的。 这是 xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="qualified">
<!-- Main element -->
<xs:element name="program">
<xs:complexType>
<xs:sequence>
<xs:element name="scriptList">
<xs:complexType>
<xs:sequence>
<xs:element name="script" type="script" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="script" />
<xs:complexType name="StartScript">
<xs:complexContent>
<xs:extension base="script">
<xs:all>
<xs:element name="isUserScript" type="xs:boolean"></xs:element>
</xs:all>
</xs:extension>
</xs:complexContent>
</xs:complexType>
一个简单的解决方案是 运行 在输入 XML 上进行字符串替换(“type=\”“到”xsi:type=\“”),但这很漂亮丑陋的。 有更好的解决方案吗?
您可以将 XML 加载到中间 LINQ to XML XDocument
中,修复 <script>
元素上的属性命名空间,然后直接反序列化为最终的 class:
// Load to intermediate XDocument
XDocument xDoc;
using (var reader = XmlReader.Create(f))
xDoc = XDocument.Load(reader);
// Fix namespace of "type" attributes
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
foreach (var element in xDoc.Descendants("script"))
{
var attr = element.Attribute("type");
if (attr == null)
continue;
var newAttr = new XAttribute(xsi + attr.Name.LocalName, attr.Value);
attr.Remove();
element.Add(newAttr);
}
// Deserialize directly to final class.
var program = xDoc.Deserialize<program>();
使用扩展方法:
public static class XObjectExtensions
{
public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null)
{
if (element == null)
throw new ArgumentNullException();
using (var reader = element.CreateReader())
return (T)(serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader);
}
}