1

I'm using .NET C# XML and LINQ to Update/delete/insert my XML file.

I've got an XML file looks like below (image1) and I would like to inlcude just the 2nd XML file.

The first XML file is the original file and I don't want to touch this file. So I prefer a reference to a 2nd. file (external file) so I can add/remove XML lines there in stead of the Mainf XML file.

But how can do include or merge the 2nd XML (External file) in to the FIRST? I just need to the tags (see RED box) from see in RED box.

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

Question:

1- What do I need to write for code in XML file 1 so my code in XMLfile 2 (external file) is included?

2- How should my XMLfile 2 (external file) look like? In fact I need the tags I think, because I'm reading the XML XDocument xdoc = XDocument.Load(this.Server.MapPath(path));and doing some update/deletes.....

Original file

IMAG2 - EXTERNAL FILE enter image description here

ethem
  • 2,888
  • 9
  • 42
  • 57

2 Answers2

4

Well adding elements from a second file is easy:

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"));

On the other hand the term "merging" suggests you might want to do something more complex like identifying elements based on some id or key and then not simply add new elements but overwrite some data. You will need to provide more details on exactly what kind of merge process you want if you need help with writing the code.

[edit] Here is an example on how to use the DTD based mechanism of a reference to an external entity to include an XML fragment file into another document: file1.xml is as follows:

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

fragment.xml is as follows:

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

Then, when reading in the main file with LINQ to XML and .NET 4.0 you need to make sure the XmlReader you use is set to parse the DTD e.g.

        XDocument doc;
        using (XmlReader xr = XmlReader.Create("file1.xml", new XmlReaderSettings() { DtdProcessing = System.Xml.DtdProcessing.Parse }))
        {
            doc = XDocument.Load(xr);
        }
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • thank you, you posted usefull code. But the my concern is: file1.xml is used by other third party application too and I don't want to do delete/add operation directly in this file (maybe just inlcude a reference to external file). so I would like to do the update/delete/add in file2.xml only... Is this way possible? – ethem Sep 19 '11 at 11:16
  • The W3C has an XML inclusion mechanism XInclude http://www.w3.org/TR/xinclude/ but Microsoft's XML parsers don't support that. The only approach supported is DTD based use of references to external entities. I will post an example on how to use that with LINQ to XML. – Martin Honnen Sep 19 '11 at 15:36
  • For this to work with external files, you must provide a XmlResolver (just use new XmlUrlResolver) as stated here: https://stackoverflow.com/a/6618275/304820 – TheRoadrunner Aug 16 '17 at 08:53
2

There is a better approach with the XInclude W3C Tag. Here is my Linq to XML extention method:

/// <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
}

The code was inspired by following blog post: http://catarsa.com/Articles/Blog/Any/Any/Linq-To-Xml-XInclude?MP=pv

Further XInclude infos: http://msdn.microsoft.com/en-us/library/aa302291.aspx

Benni
  • 203
  • 2
  • 7
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – arne Dec 09 '13 at 15:25