XNamespace和XElement在第一个子元素上添加一个空的xmlns属性

时间:2018-07-05 23:09:13

标签: c# soap linq-to-xml xelement

我正在尝试使用XElement创建以下XML字符串

<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,因为我需要动态构建我的soap请求主体:

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

我无法使用Web服务引用来执行此操作,因为从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 :(得分:1)

在XML中,当元素没有指定名称空间时,则它继承其最近的具有名称空间的祖先的名称空间。因此,在示例XML中,p元素及其子元素实际上都与Issue处于同一命名空间中,因为它们在xmlns的情况下没有Issue属性。

要使用XElement创建相同的结构,则需要确保 all 元素指定与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上指定,则实际上是在说您根本不希望内部元素具有名称空间。从而在第一个子元素上产生一个空的{{1}}属性:它实际上是在“退出”父名称空间。