如何将外部XML包含到XML文件中 - 两个文件应该如何

时间:2011-09-19 10:35:32

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

我正在使用.NET C#XML和LINQ来更新/删除/插入我的XML文件。

我有一个XML文件,如下图(image1),我想仅仅包含第二个XML文件。

第一个XML文件是原始文件,我不想触摸此文件。所以我更喜欢参考第二个。文件(外部文件)所以我可以在那里添加/删除XML行而不是Mainf XML文件。

但是如何将第二个XML(外部文件)包含或合并到FIRST中呢? 我只需要看到红色框中的标签(参见RED框)。

<RewriterRule>
   <LookFor>        </LookFor>
   <SendTo>         </SendTo>
</RewriterRule>

问题:

1-我需要为XML文件1中的代码编写什么,以便包含XMLfile 2(外部文件)中的代码?

2-我的XMLfile 2(外部文件)应该如何?事实上我需要我认为的标签,因为我正在阅读XML XDocument xdoc = XDocument.Load(this.Server.MapPath(path));并做一些更新/删除......

Original file

IMAG2 - 外部文件 enter image description here

2 个答案:

答案 0 :(得分:4)

从第二个文件添加元素很容易:

XDocument doc1 = XDocument.Load(MapPath("file1.xml"));
doc1.Root.Element("Rules").Add(XDocument.Load(MapPath("file2.xml")).Root.Element("Rules").Elements("RewriterRule"));

// now save to third file with e.g.
doc1.Save(MapPath("updated.xml"));
// or overwrite first file e.g.
doc1.Save(MapPath("file1.xml"));

另一方面,术语“合并”表明你可能想要做一些更复杂的事情,比如根据某些id或键识别元素,然后不是简单地添加新元素而是覆盖一些数据。如果您需要编写代码的帮助,则需要提供有关所需合并过程的详细信息。

[edit]下面是一个示例,介绍如何使用基于DTD的外部实体引用机制将XML片段文件包含到另一个文档中:file1.xml如下:

<!DOCTYPE example [
  <!ENTITY e1 SYSTEM "fragment.xml">
]>
<example>
  <data>
    <item>1</item>
    &e1;
  </data>
</example>

fragment.xml如下:

<?xml version="1.0" encoding="utf-8" ?>
<item>2</item>

然后,当使用LINQ to XML和.NET 4.0读取主文件时,您需要确保您使用的XmlReader设置为解析DTD,例如。

        XDocument doc;
        using (XmlReader xr = XmlReader.Create("file1.xml", new XmlReaderSettings() { DtdProcessing = System.Xml.DtdProcessing.Parse }))
        {
            doc = XDocument.Load(xr);
        }

答案 1 :(得分:1)

XInclude W3C标签有更好的方法。这是我的Linq to XML扩展方法:

/// <summary>
/// Linq to XML XInclude extentions
/// </summary>
public static class XIncludeExtention
{
    #region fields

    /// <summary>
    /// W3C XInclude standard
    /// Be aware of the different 2001 and 2003 standard.
    /// </summary>
    public static readonly XNamespace IncludeNamespace = "http://www.w3.org/2003/XInclude";

    /// <summary>
    /// Include element name
    /// </summary>
    public static readonly XName IncludeElementName = IncludeNamespace + "include";

    /// <summary>
    /// Include location attribute
    /// </summary>
    public const string IncludeLocationAttributeName = "href";

    /// <summary>
    /// Defines the maximum sub include count of 25
    /// </summary>
    public const int MaxSubIncludeCountDefault = 25;

    #endregion


    #region methods


    /// <summary>
    /// Replaces XInclude references with the target content.
    /// W3C Standard: http://www.w3.org/2003/XInclude
    /// </summary>
    /// <param name="xDoc">The xml doc.</param>
    /// <param name="maxSubIncludeCount">The max. allowed nested xml includes (default: 25).</param>
    public static void ReplaceXIncludes(this XDocument xDoc, int maxSubIncludeCount = MaxSubIncludeCountDefault)
    {
        ReplaceXIncludes(xDoc.Root, maxSubIncludeCount);
    }

    /// <summary>
    /// Replaces XInclude references with the target content.
    /// W3C Standard: http://www.w3.org/2003/XInclude
    /// </summary>
    /// <param name="xmlElement">The XML element.</param>
    /// <param name="maxSubIncludeCount">The max. allowed nested xml includes (default: 25).</param>
    public static void ReplaceXIncludes(this XElement xmlElement, int maxSubIncludeCount = MaxSubIncludeCountDefault)
    {
        xmlElement.ReplaceXIncludes(1, maxSubIncludeCount);
    }

    private static void ReplaceXIncludes(this XElement xmlElement, int subIncludeCount, int maxSubIncludeCount)
    {
        var results = xmlElement.DescendantsAndSelf(IncludeElementName).ToArray<XElement>();    // must be materialized

        foreach (var includeElement in results)
        {
            var path = includeElement.Attribute(IncludeLocationAttributeName).Value;
            path = Path.GetFullPath(path);

            var doc = XDocument.Load(path);
            if (subIncludeCount <= maxSubIncludeCount)  // protect mutal endless references
            {
                // replace nested includes
                doc.Root.ReplaceXIncludes(++subIncludeCount, maxSubIncludeCount);
            }
            includeElement.ReplaceWith(doc.Root);
        }
    }

    #endregion
}

该代码的灵感来自以下博文: http://catarsa.com/Articles/Blog/Any/Any/Linq-To-Xml-XInclude?MP=pv

进一步XInclude的相关信息: http://msdn.microsoft.com/en-us/library/aa302291.aspx