Как создать XElement с пространством имен по умолчанию для детей без использования XNamespace во всех дочерних узлах - PullRequest
9 голосов
/ 25 января 2009

Я пытаюсь использовать System.Xml.Linq для создания документов XHTML. Таким образом, подавляющее большинство узлов в моих деревьях должны использовать это пространство имен:

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

Я могу достаточно легко создать XElement узлов, ограниченных этим пространством имен, используя XNamespace, например:

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

Однако я не хочу, чтобы XNamespace был доступен во всем коде, который создает узлы HTML, и должен префиксировать каждое XElementXAttribute) имя, которое я создаю соответственно. *

Текстовый формат XML сам по себе учитывает это требование и позволяет устанавливать пространство имен по умолчанию в предке, которое наследуется потомками, используя зарезервированный атрибут xmlns. Я хотел бы сделать что-то подобное, используя System.Xml.Linq.

Возможно ли это?

Ответы [ 3 ]

5 голосов
/ 07 февраля 2009

Я решил использовать статический класс с именем 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 (здесь показан не весь мой класс).

3 голосов
/ 28 мая 2010

Я выбрал рекурсивный путь переписывания. Вам не нужно «реконструировать» дерево. Вы можете просто поменять имена узлов (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);
        }
    }
1 голос
/ 25 января 2009

Проблема в том, что XName, используемое для создания XElement, должно указывать правильное пространство имен. Я хотел бы создать статический класс, подобный этому: -

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 независимо от того, используете ли вы их, но преимуществом является преобразование пространства имен + «тэг» происходит только один раз. Я не уверен, что это преобразование было бы оптимизировано иначе. Я уверен, что XNames создаются только один раз: -

XNamepace n = "http://www.w3.org/1999/xhtml";
XNames x = n + "A";
XName y = n + "A";
Object.ReferenceEquals(x, y) //is true.
...