【问题标题】:How to load and add elements in an XML tree如何在 XML 树中加载和添加元素
【发布时间】:2015-12-04 18:18:26
【问题描述】:

最近几天我在这里阅读 Stack Overflow、博客和 MSDN 文章。我显然对命名空间、Linq 和 XML 的工作方式缺乏一些基本的了解,因此需要帮助。如果我有更多的头发要拔掉,它现在就在我手中:-)

使用 C# 和 Linq to XML,我打开以下 opf.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<package version="2.0" xmlns="http://www.idpf.org/2007/opf" unique-identifier="">
  <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
  </metadata>
  <manifest></manifest>
  <spine toc="ncx"></spine>
  <guide></guide>
</package>

我用以下代码打开这个文件:

File.Copy(_opfFile, opfFile, true);
XDocument opfDoc = XDocument.Load(opfFile);

不幸的是,我在这里完全迷路了。我需要做的是在每个主要节点下生成元素。对于metadata 节点,我需要创建具有命名空间和非命名空间的元素。对于文件的其余部分,我只需要添加不使用命名空间的常规节点。

下面是我想要实现的输出示例。我敢肯定,如果你能帮助我处理 metdatamanifest 节点,我可以弄清楚如何更新其余节点。

<?xml version="1.0" encoding="UTF-8"?>
<package xmlns:ibooks="http://www.idpf.org/2007/opf" unique-identifier="BookId" version="3.0" prefix="ibooks: http://www.idpf.org/2007/opf" 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">
        <dc:title>Untitled</dc:title>
        <meta refines="#contributor" property="role" scheme="marc:relators">bkp</meta>
    </metadata>
    <manifest>
        <item id="toc" href="toc.xhtml" media-type="application/xhtml+xml" properties="nav"/>
    </manifest>
    <spine toc="ncx"></spine>
    <guide></guide>
</package>

您能否提供一些基本的 C#/Linq 代码:

  1. 如上例所示,查找并添加需要“dc”命名空间 (ns) 的 metadata 项目。
  2. 添加一个不使用上例中命名空间的metadata 项。
  3. 添加一个新的manifest 项目,如上例所示。

我会分享我编写的代码,但它到处都是,而且我有很多注释代码。我可以告诉你的是,我经常会遇到空异常错误。

提前谢谢你。

【问题讨论】:

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


    【解决方案1】:

    在对使用多个命名空间的 XML 进行逆向工程时,我发现以下调试实用程序很有用:

    public static class XObjectExtensions
    {
        public static IEnumerable<string> DumpXmlAttributeNames(this XObject obj)
        {
            if (obj is XAttribute)
                return new[] { ((XAttribute)obj).Name.ToString() };
            else if (obj is XElement)
            {
                return ((XElement)obj).Attributes().Select(a => a.Name.ToString());
            }
            return Enumerable.Empty<string>();
        }
    
        public static IEnumerable<string> DumpXmlElementNames(this XElement root)
        {
            if (root == null)
                return Enumerable.Empty<string>();
            return root.DescendantsAndSelf().Select(el => string.Format("{0} \"{1}\"; Attribute names: {2}",
                new string(' ', el.AncestorsAndSelf().Count()), el.Name.ToString(), String.Join(", ", el.DumpXmlAttributeNames().Select(s => "\"" + s + "\""))));
        }
    
        public static IEnumerable<string> DumpXmlElementNames(this XDocument root)
        {
            if (root == null)
                return Enumerable.Empty<string>();
            return root.Root.DumpXmlElementNames();
        }
    }
    

    使用它们,您可以轻松查看所需 XML 的元素和属性的正确命名空间:

      "{http://www.idpf.org/2007/opf}package"; Attribute names: "{http://www.w3.org/2000/xmlns/}ibooks", "unique-identifier", "version", "prefix", "xmlns"
       "{http://www.idpf.org/2007/opf}metadata"; Attribute names: "{http://www.w3.org/2000/xmlns/}dc", "{http://www.w3.org/2000/xmlns/}opf"
        "{http://purl.org/dc/elements/1.1/}title"; Attribute names: 
        "{http://www.idpf.org/2007/opf}meta"; Attribute names: "refines", "property", "scheme"
       "{http://www.idpf.org/2007/opf}manifest"; Attribute names: 
        "{http://www.idpf.org/2007/opf}item"; Attribute names: "id", "href", "media-type", "properties"
       "{http://www.idpf.org/2007/opf}spine"; Attribute names: "toc"
       "{http://www.idpf.org/2007/opf}guide"; Attribute names: 
    

    因此您需要在"http://purl.org/dc/elements/1.1/" 命名空间中添加"title" 元素,在"http://www.idpf.org/2007/opf" 命名空间中添加其他元素:

            var dc = (XNamespace)"http://purl.org/dc/elements/1.1/";
            var opf = (XNamespace)"http://www.idpf.org/2007/opf";
    
            var meta = opfDoc.Root.Element(opf + "metadata");
            meta.Add(new XElement(dc + "title", "Untitled"));
            meta.Add(new XElement(opf + "meta", 
                new XAttribute("refines", "#contributor"), 
                new XAttribute("property", "role"), 
                new XAttribute("scheme", "marc:relators"), "bkp"));
    
            var manifest = opfDoc.Root.Element(opf + "manifest");
            manifest.Add(new XElement(opf + "item", 
                new XAttribute("id", "toc"), 
                new XAttribute("href", "toc.xhtml"), 
                new XAttribute("media-type", "application/xhtml+xml"), 
                new XAttribute("properties", "nav")));
    

    【讨论】:

    • 非常感谢您为我安排了这一切。我不能告诉你这有多大帮助。第一次复制和粘贴此代码时,我正在摇头。你不知道我为了完成这项任务而编写并丢弃了多少代码。您的XObjectExtensions 课程帮助我终于“得到”了它。谢谢你让我周末回来:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 2012-06-14
    • 1970-01-01
    相关资源
    最近更新 更多