2013-08-19 102 views
0

我有许多类似XML的结构的文件,但是具有未定义的名称空间前缀。我只需要从这些文件中提取数据,而不是验证它们。当试图用XElement.LoadXDocument.Load解析时,我得到一个undefined prefix异常。我如何做到这一点(LINQ to XML优先)?解析带有未定义名称空间前缀的(psuedo-)XML

回答

1

如果您提前知道前缀,请将它们自己添加到虚拟根节点并将该文档添加到该虚拟节点。然后你可以解析和查询你的实际文档。但是,您必须将其添加到未加以解析的XML内容之前它被加载/解析。幸运的是,这可以相对简单地完成。

例如,

XElement ParseFragment(string fragment, IDictionary<string, XNamespace> namespaces) 
{ 
    var namespaceDefs = namespaces 
     .Select(kvp => String.Format("xmlns:{0}=\"{1}\"", kvp.Key, kvp.Value.NamespaceName)); 
    var xml = String.Format(
     "<root {0}>{1}</root>", 
     String.Join(" ", namespaceDefs), 
     fragment); 
    var root = XElement.Parse(xml); 
    return root.Elements().Single(); 
} 
XElement LoadFragment(TextReader fragmentReader, IDictionary<string, XNamespace> namespaces) 
{ 
    var namespaceDefs = namespaces 
     .Select(kvp => String.Format("xmlns:{0}=\"{1}\"", kvp.Key, kvp.Value.NamespaceName)); 
    var sb = new StringBuilder(); 
    sb.AppendLine(String.Format("<root {0}>", String.Join(" ", namespaceDefs))); 
    sb.AppendLine(fragmentReader.ReadToEnd()); 
    sb.AppendLine("</root>"); 
    var root = XElement.Load(new StringReader(sb.ToString())); 
    return root.Elements().Single(); 
} 

然后你就可以解析/加载和查询元素:

var fragment = @"<a:root><b:child>foo</b:child><b:child>bar</b:child></a:root>"; 
var namespaces = new Dictionary<string, XNamespace> 
{ 
    { "a", "http://a.com" }, 
    { "b", "http://b.com" }, 
}; 
var element = ParseFragment(fragment, namespaces); 
var b = namespaces["b"]; 
var childValues = element 
    .Descendants(b + "child") 
    .Select(child => (string)child); 
+0

如果我不事先知道的前缀,我有重复尝试解析,并根据错误消息添加一个名称空间。我会试试这个。 –

相关问题