how to include external XML into the XML file- how should both file look like
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.....
IMAG2 - EXTERNAL FILE
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);
}
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
精彩评论