如何在不使用所有子节点中的XNamespace的情况下为子节点创建具有默认命名空间的XElement

我正在尝试使用System.Xml.Linq来创建XHTML文档。 因此,我树中的绝大多数节点都应该使用这个命名空间:

 http://www.w3.org/1999/xhtml 

我可以使用XNamespace轻松地创建作用于此命名空间的XElement节点,如下所示:

 XNamespace xhtml = "http://www.w3.org/1999/xhtml"; // ... new XElement(xhtml + "html", // ... 

但是,我不希望在创建HTML节点的所有代码中都提供XNamespace ,并且必须为我创建的每个单独的XElement (和XAttribute )名称添加前缀。

XML文本格式本身考虑了这一要求,并允许使用保留的xmlns属性在后代inheritance的祖先中设置默认命名空间。 我想使用System.Xml.Linq做类似的事情。

这可能吗?

我决定使用一个名为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; } } 

这似乎是最干净的做事方式,特别是当我可以添加方便例程时,例如XHtml.A方法(不是我的所有类都显示在这里)。

我采用了递归重写路径。 你真的不需要’重建’树。 您只需换出节点名称( 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); } } 

问题是用于创建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 } 

现在你可以像这样构建一个xhtml文档: –

 XDocument doc = new XDocument( new XElement(XHtml.Html, new XElement(XHtml.Body) ) ); 

该静态类的另一种方法是: –

 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"; } 

无论你是否使用它们,这都有实例化所有可能的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.