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

时间:2009-01-25 17:34:57

标签: c# .net xml namespaces linq-to-xml

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

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

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

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

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

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

这可能吗?

3 个答案:

答案 0 :(得分:5)

我决定使用名为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方法(这里没有显示我的所有类)。

答案 1 :(得分:3)

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

答案 2 :(得分:1)

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