XElement 不应该从其父 Xelement 继承命名空间吗?

Posted

技术标签:

【中文标题】XElement 不应该从其父 Xelement 继承命名空间吗?【英文标题】:Shouldn't an XElement inherit the namespace from its parent Xelement? 【发布时间】:2011-02-11 17:41:36 【问题描述】:

我第一次在 .NET 3.5 中使用 Linq for XML,但在命名空间方面遇到了一些问题。即,XElement 是这样打印的:<opf:metadata> 当我只想说<metadata>

代码如下:

    XNamespace opfNamespace = "http://www.idpf.org/2007/opf";
        XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
        XNamespace dcterms = "http://purl.org/dc/terms/";
        XNamespace dc = "http://purl.org/dc/elements/1.1/";

        opfRoot = new XElement(opfNamespace + "package",
                                    new XAttribute("version", "2.0"),
                                    new XAttribute("unique-identifier", "uuid_id"));
        XElement metadata = new XElement(opfNamespace + "metadata",
                                    new XAttribute(XNamespace.Xmlns + "xsi", xsi),
                                    new XAttribute(XNamespace.Xmlns + "opf", opfNamespace),
                                    new XAttribute(XNamespace.Xmlns + "dcterms", dcterms),
                                    new XAttribute(XNamespace.Xmlns + "dc", dc),
                                    new XElement(dc + "language", "pt-BR"));
        opfRoot.Add(metadata);

结果如下:

<?xml version="1.0" encoding="utf-8"?>
<package version="2.0" unique-identifier="uuid_id" xmlns="http://www.idpf.org/2007/opf">
  <opf:metadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:opf="http://www.idpf.org/2007/opf" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dc="http://purl.org/dc/elements/1.1/">
    <dc:language>pt-BR</dc:language>
  </opf:metadata>
</package>

我希望元数据元素没有 opf: "opf:metadata"

如果我从 opfNameSpace + "metadata" 中删除 opfNameSpace,我会在元数据元素中得到一个空白的 xmlns 命名空间 (xmlns="")。

我看了这个帖子:

How can I write xml with a namespace and prefix with XElement?

还有这个:

XElement default namespace on attributes provides unexpected behaviour

但他们没有解决我的问题。有什么想法吗?

【问题讨论】:

【参考方案1】:

这是因为您在元数据元素中重新声明了 opf 命名空间别名。只需删除此属性:

new XAttribute(XNamespace.Xmlns + "opf", opfNamespace)

来自&lt;metadata&gt; 构造函数调用,它工作正常:

<package version="2.0" unique-identifier="uuid_id"
         xmlns="http://www.idpf.org/2007/opf">
  <metadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dcterms=
"http://purl.org/dc/terms/" xmlns:dc="http://purl.org/dc/elements/1.1/">
    <dc:language>pt-BR</dc:language>
  </metadata>
</package>

现在您可能会争辩说,因为您要重新声明名称空间别名以使其具有与以前相同的 URL,所以这应该是无关紧要的 - 老实说,我不知道规范对此有何规定。但这似乎有些合理。

另一方面,我相信这两种 XML 表单最终应该被任何解析它们的东西同等对待,所以如果使用所有相关声明创建 metadata 元素更方便,那么它不应该导致任何问题... AFAIK :)

【讨论】:

好的,这行得通。我想在元数据标签中保留 'xmlns:opf="​​idpf.org/2007/opf"',但我认为它是多余的。【参考方案2】:

删除new XAttribute(XNamespace.Xmlns + "opf", opfNamespace),

【讨论】:

你怎么知道它是第一个回答的?两者都显示相同的时间戳。我标记了另一个,因为它更完整。【参考方案3】:

由于我需要的命名空间格式非常具体,即使解决了 opf:metadata 问题也没有正确生成,我找到了更好的方法。我刚刚手动创建了一个 XmlDocument,并添加了 XML。从那里我可以以编程方式对其进行编辑。像这样:

            XmlDocumentopf = new XmlDocument();
            opf.LoadXml("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" +
                            "<package version=\"2.0\" unique-identifier=\"uuid_id\" xmlns=\"http://www.idpf.org/2007/opf\">" +
                            "<metadata xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:opf=\"http://www.idpf.org/2007/opf\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:dcterms=\"http://purl.org/dc/terms/\">" +
                            "<dc:title>Title of this book</dc:title>" +
                            "<dc:language>pt-BR</dc:language>" +
                            "<dc:identifier id=\"uuid_id\" opf:scheme=\"uuid\">a335de4c-560f-4b75-bcba-1418b726f92c</dc:identifier>" +
                            "<dc:creator opf:role=\"aut\">Desconhecido(a)</dc:creator>" +
                            "<dc:date>2011-01-31T11:59:46.949000+00:00</dc:date>" +
                            "<meta name=\"cover\" content=\"book-cover\"/>" +
                            "</metadata>" +
                            "<manifest />" +
                            "<spine toc=\"ncx\" />" +
                            "<guide />" +
                            "</package>");

【讨论】:

以上是关于XElement 不应该从其父 Xelement 继承命名空间吗?的主要内容,如果未能解决你的问题,请参考以下文章

从具有多个命名空间的 XElement 中获取元素

C# - 如何从 XElement 中删除 xmlns

从 XElement 获取子元素 [重复]

从 XElement 中删除属性

Linq-to-XML XElement.Remove() 留下不需要的空白

C# linq 从 XElement 树中选择重复项