C# 如何在不使用 XNamespace 的所有子节点中为子节点创建具有默认命名空间的 XElement
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/477962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create XElement with default namespace for children without using XNamespace in all child nodes
提问by Barry Kelly
I'm trying to use System.Xml.Linq
to create XHTML documents. Thus, the vast majority of the nodes in my trees ought to use this namespace:
我正在尝试使用System.Xml.Linq
来创建 XHTML 文档。因此,我的树中的绝大多数节点都应该使用这个命名空间:
http://www.w3.org/1999/xhtml
I can create XElement
nodes scoped to this namespace easily enough, using an XNamespace
, like this:
我可以XElement
很容易地创建作用域到这个命名空间的节点,使用XNamespace
,像这样:
XNamespace xhtml = "http://www.w3.org/1999/xhtml";
// ...
new XElement(xhtml + "html", // ...
However, I don't want to have to make an XNamespace
available throughout all the code that creates HTML nodes, and have to prefix every single XElement
(and XAttribute
) name I create accordingly.
但是,我不想让XNamespace
所有创建 HTML 节点的代码都可用,并且必须相应地为我创建的每个XElement
(和XAttribute
)名称添加前缀。
The XML text format itself takes this requirement into account, and permits setting a default namespace in an ancestor which is inherited by descendants, using the reserved xmlns
attribute. I'd like to do something similar using System.Xml.Linq
.
XML 文本格式本身考虑了这一要求,并允许使用保留xmlns
属性在后代继承的祖先中设置默认名称空间。我想使用System.Xml.Linq
.
Is this possible?
这可能吗?
采纳答案by Barry Kelly
I've decided to use a static class called XHtml
, that looks like this:
我决定使用一个名为 的静态类XHtml
,它看起来像这样:
public static class XHtml
{
static XHtml()
{
Namespace = "http://www.w3.org/1999/xhtml";
}
public static XNamespace Namespace { get; private set; }
public static XElement Element(string name)
{
return new XElement(Namespace + name);
}
public static XElement Element(string name, params object[] content)
{
return new XElement(Namespace + name, content);
}
public static XElement Element(string name, object content)
{
return new XElement(Namespace + name, content);
}
public static XAttribute Attribute(string name, object value)
{
return new XAttribute(/* Namespace + */ name, value);
}
public static XText Text(string text)
{
return new XText(text);
}
public static XElement A(string url, params object[] content)
{
XElement result = Element("a", content);
result.Add(Attribute("href", url));
return result;
}
}
This seems to be the cleanest way of doing things, particularly as I can then add in convenience routines, such as the XHtml.A
method (not all of my class is shown here).
这似乎是最干净的做事方式,特别是因为我可以添加方便的例程,例如XHtml.A
方法(此处未显示我的所有类)。
回答by AnthonyWJones
The problem is the the XName used to create the XElement needs to specify the correct namespace. What I would be tempted to do is create a static class like this:-
问题是用于创建 XElement 的 XName 需要指定正确的命名空间。我想做的是创建一个像这样的静态类:-
public static class XHtml
{
public static readonly XNamespace Namespace = "http://www.w3.org/1999/xhtml";
public static XName Html { get { return Namespace + "html"; } }
public static XName Body { get { return Namespace + "body"; } }
//.. other element types
}
Now you can build a xhtml doc like this:-
现在您可以像这样构建一个 xhtml 文档:-
XDocument doc = new XDocument(
new XElement(XHtml.Html,
new XElement(XHtml.Body)
)
);
An alternative approach to that static class would be:-
该静态类的另一种方法是:-
static class XHtml
{
public static readonly XNamespace Namespace = "http://www.w3.org/1999/xhtml";
public static readonly XName Html = Namespace + "html";
public static readonly XName Body = Namespace + "body";
}
This has the downside of instancing all the possible XName regardless of whether you use them but the upside is the conversion of Namespace + "tagname" only happens once. I'm not sure this conversion would be optimised out otherwise. I am sure that XNames are only instanced once:-
这具有实例化所有可能的 XName 的缺点,无论您是否使用它们,但优点是 Namespace + "tagname" 的转换只发生一次。我不确定这个转换是否会被优化掉。我确信 XNames 只实例化一次:-
XNamepace n = "http://www.w3.org/1999/xhtml";
XNames x = n + "A";
XName y = n + "A";
Object.ReferenceEquals(x, y) //is true.
回答by Julian Lettner
I took the recursively rewriting path. You do not really have to 'reconstruct' the tree. You can just swap out the node names (XName
).
我采用了递归重写路径。您实际上不必“重建”树。您可以只换出节点名称 ( XName
)。
private static void ApplyNamespace(XElement parent, XNamespace nameSpace)
{
if(DetermineIfNameSpaceShouldBeApplied(parent, nameSpace))
{
parent.Name = nameSpace + parent.Name.LocalName;
}
foreach (XElement child in parent.Elements())
{
ApplyNamespace(child, nameSpace);
}
}