<div xmlns="http://www.com">
<div class="child">
</div>
</div>
当我使用xpath获取子元素并执行.ToString()
时,它会向其添加父命名空间。如何在没有冗余命名空间的情况下获取内容?
答案 0 :(得分:3)
您可以使用此扩展方法。它将以递归方式创建另一个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());
}
答案 1 :(得分:1)
Raman的答案很好,但它不适用于这样的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;
}
答案 2 :(得分:0)
这里提供的答案都不适合我。对于那里的其他任何人,使用我自己的大型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