XNamespace и XElement добавляют пустой атрибут xmlns в первый дочерний элемент - PullRequest
0 голосов
/ 06 июля 2018

Я пытаюсь создать следующую XML-строку, используя XElement

<Issue xmlns="http://tempuri.org/">
    <p>
        <Nombre>no</Nombre>
        <Descripcion>asdf</Descripcion>
    </p>
</Issue>

Я пробовал следующий код, но этот подход добавляет пустой атрибут xmlns к элементу p, который мне не нужен:

var ns = XNamespace.Get("http://tempuri.org/");

XElement e = new XElement(ns + "Issues",
                          new XElement("p", new XElement("Nombre", "nme"), 
                                            new XElement("Descripcion", "dsc")));

Как я могу предотвратить эту проблему?

ПРИМЕЧАНИЕ :

Я не могу использовать XElement.Parse вот так, потому что мне нужно динамически построить тело запроса на мыло:

var body = XElement.Parse("<Issue xmlns=\"http://tempuri.org/\"><p><Nombre>no</Nombre><Descripcion>asdf</Descripcion></p></Issue>");

Я не могу сделать это со ссылкой на веб-сервис, потому что существует ошибка, когда существует ссылка из Xamarin.


Пока я использую следующий обходной путь, но это не лучшее решение, я думаю:

var xdoc = new XmlDocument();
var xissue = xdoc.CreateElement("Issue");

var attr = xdoc.CreateAttribute("xmlns");
attr.Value = "http://tempuri.org/";
xissue.Attributes.Append(attr);

var xp = xdoc.CreateElement("p");
xissue.AppendChild(xp);

var xnombre = xdoc.CreateElement("Nombre");
xnombre.InnerText = "any value";
xp.AppendChild(xnombre);

var xdescription = xdoc.CreateElement("Descripcion");
xdescription.InnerText = "any value";
xp.AppendChild(xdescription);

var e = XElement.Parse(xissue.OuterXml);

1 Ответ

0 голосов
/ 12 ноября 2018

В XML, когда элементу не определено пространство имен, он наследует пространство имен своего ближайшего предка, который имеет пространство имен. Итак, в вашем примере XML элемент p и его дочерние элементы фактически находятся в том же пространстве имен, что и Issue, поскольку они не имеют атрибута xmlns, в то время как Issue.

Чтобы создать эту же структуру, используя XElement, вам необходимо убедиться, что все элементы задают то же пространство имен, что и Issue:

var ns = XNamespace.Get("http://tempuri.org/");

XElement e = new XElement(ns + "Issue",
                          new XElement(ns + "p", new XElement(ns + "Nombre", "nme"),
                                                 new XElement(ns + "Descripcion", "dsc")));

XElement достаточно умен, чтобы признать, что при преобразовании в строку ему не нужно повторять атрибут xmlns, если он совпадает с атрибутом его родителя.

Скрипка: https://dotnetfiddle.net/QzYPoK

И наоборот, если вы просто указываете пространство имен на внешнем XElement, но не на внутреннем, вы фактически говорите, что не хотите, чтобы у внутренних элементов было пространство имен вообще. В результате получается пустой атрибут xmlns в первом дочернем элементе: он фактически «отказывается» от родительского пространства имен.

...