<div xmlns="http://www.com">
<div class="child">
</div>
</div>
当我使用 xpath 获取子元素并执行.ToString()
时,它会将父命名空间添加到它。如何在没有冗余名称空间的情况下获取内容?
<div xmlns="http://www.com">
<div class="child">
</div>
</div>
当我使用 xpath 获取子元素并执行.ToString()
时,它会将父命名空间添加到它。如何在没有冗余名称空间的情况下获取内容?
您可以使用此扩展方法。它将递归地创建另一个 XElement,包括其没有命名空间的子元素。扩展方法需要放在静态类中:
public static XElement IgnoreNamespace(this XElement xelem)
{
XNamespace xmlns = "";
var name = xmlns + xelem.Name.LocalName;
return new XElement(name,
from e in xelem.Elements()
select e.IgnoreNamespace(),
xelem.Attributes()
);
}
static void Main(string[] args)
{
var document = XDocument.Parse("<?xml version=\"1.0\" ?><div xmlns=\"http://www.ya.com\"><div class=\"child\"></div></div>");
var first = document.Root.Elements().First().IgnoreNamespace();
Console.WriteLine(first.ToString());
}
拉曼的答案很好,但它不适用于这样的 XML:
<div xmlns="http://www.ya.com">
<div class="child">
**This is some text**
</div>
</div>
这是我改进的版本,可以工作:
public static XElement IgnoreNamespace(this XElement xelem)
{
XNamespace xmlns = "";
var name = xmlns + xelem.Name.LocalName;
var result = new XElement(name,
from e in xelem.Elements()
select e.IgnoreNamespace(),
xelem.Attributes()
);
if (!xelem.HasElements)
result.Value = xelem.Value;
return result;
}
这里提供的答案都不适合我。对于在这里登陆的其他任何人,使用我自己的大型 xaml 文件和代码片段中包含的示例进行测试。
void Main()
{
var path = @"C:\Users\User\AppData\Local\Temp\sample.xml";
var text = File.ReadAllText(path);
var surrounded = "<test xmlns=\"http://www.ya.com\">" + text + "</test>";
var xe = XElement.Parse(surrounded);
xe.Dump();
xe.StripNamespaces().Dump();
var sampleText = "<test xmlns=\"http://www.ya.com\"><div class=\"child\" xmlns:diag=\"http://test.com\"> ** this is some text **</div></test>";
xe = XElement.Parse(sampleText);
xe.Dump();
xe.StripNamespaces().Dump();
}
public static class Extensions
{
public static XNode StripNamespaces(this XNode n)
{
var xe = n as XElement;
if(xe == null)
return n;
var contents =
// add in all attributes there were on the original
xe.Attributes()
// eliminate the default namespace declaration
.Where(xa => xa.Name.LocalName != "xmlns")
.Cast<object>()
// add in all other element children (nodes and elements, not just elements)
.Concat(xe.Nodes().Select(node => node.StripNamespaces()).Cast<object>()).ToArray();
var result = new XElement(XNamespace.None + xe.Name.LocalName, contents);
return result;
}
#if !LINQPAD
public static T Dump<T>(this T t, string description = null)
{
if(description != null)
Console.WriteLine(description);
Console.WriteLine(t);
return t;
}
#endif
}
首先写成F#
:
let stripNamespaces (e:XElement):XElement=
// if the node is not XElement, pass through
let rec stripNamespaces (n:XNode): XNode =
match n with
| :? XElement as x ->
let contents =
x.Attributes()
// strips default namespace, but not other declared namespaces
|> Seq.filter(fun xa -> xa.Name.LocalName <> "xmlns")
|> Seq.cast<obj>
|> List.ofSeq
|> (@) (
x.Nodes()
|> Seq.map stripNamespaces
|> Seq.cast<obj>
|> List.ofSeq
)
XElement(XNamespace.None + x.Name.LocalName, contents |> Array.ofList) :> XNode
| x -> x
stripNamespaces e :?> XElement