I have two XML files using the XML data processing files How do I connect them to each other?
Example:
members.xml
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<member id="1" username="selahattin" name="Selahattin" surname="Yüksel"/>
<member id="2" username="test" name="John" surname="Bravo"/>
</Data>
comments.xml
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<member id="1" username="selahattin" comment="Hi, stackoverflow"/>
<member id="2" username="test" comment="Hello world!"/>
</Data>
Using two XML files in the username field of the data How do you want to take this?
username==username
here is one method
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME1 = #"c:\temp\test.xml";
const string FILENAME2 = #"c:\temp\test2.xml";
static void Main(string[] args)
{
DataSet ds1 = new DataSet();
ds1.ReadXml(FILENAME1);
DataSet ds2 = new DataSet();
ds2.ReadXml(FILENAME2);
var results = from dataRows1 in ds1.Tables["member"].AsEnumerable()
join dataRows2 in ds2.Tables["member"].AsEnumerable()
on dataRows1.Field<string>("id") equals dataRows2.Field<string>("id") into ps
select dataRows1;
DataTable combinedTable = results.CopyToDataTable();
}
}
}
Related
I have an XML like this
<Root>
<Branch>
<Child Id="0">
<Reference Name="B0"/>
<Details Number="2">
<Detail Height="50"/>
<Detail Weight="3"/>
</Details>
</Child>
<Child Id="2">
<Reference Name="B2"/>
<Details Number="2">
<Detail Height="55"/>
<Detail Weight="3.5"/>
</Details>
</Child>
</Branch>
</Root>
I want to add a new block of data for Child ID=1 after Child ID=0 data block
It is probably easier to add the new child to the current list. Then sort the children. See the xml linq code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XElement newChild = new XElement("Child", new object[] {
new XAttribute("Id", "1"),
new XElement("Reference", new XAttribute("Name", "B1")),
new XElement("Details", new object[] {
new XAttribute("Number", "2"),
new XElement("Detail", new XAttribute("Height","52")),
new XElement("Detail", new XAttribute("Weight","3.25"))
})
});
XDocument doc = XDocument.Load(FILENAME);
XElement branch = doc.Descendants("Branch").FirstOrDefault();
branch.Add(newChild);
List<XElement> orderedChildren = branch.Elements("Child").OrderBy(x => (int)x.Attribute("Id")).ToList();
XElement newBranch = new XElement("Branch", orderedChildren);
branch.ReplaceWith(newBranch);
}
}
}
I am a new user on this forum and I'm not a highly experienced developer/programmer. Before asking this question, I searched and looked through Stack Overflow and some Microsoft suggested links, but I didn't find what I was looking for.
I've got the following XML file:
<?xml version="1.0" standalone="no" ?>
<WndPos name="FrontEnd.Login" l="703" r="1264" t="323" b="909" />
<LayerManager />
<ViewLayers name="RoofLayout" roof="1" nlwalls="1">
<Layer level="-1" module="1" name="Walls" locked="0" visible="1" />
</ViewLayers>
<DirProfiles>
<ProfileInfo ProfileName="ControlCQFT" JobPath="C:\Jobs" DatabasePath="D:\Database\ControlCQFT" />
</DirProfiles>
<DirHistory>
<ProfileInfo Use="Job" Path="C:\Jobs" />
</DirHistory>
I need to replace the entire <DirProfiles> node. The incoming node can be empty, which looks like <DirProfiles />. The new node that I want to insert is in the format:
<DirProfiles>
<ProfileInfo ProfileName="Control1" JobPath="D:\Client1\JobsA" DatabasePath="D:\Database\Control1" />
. . . . .
</DirProfiles>
I tried to handle the problem as a simple string replacement, but I didn't get the result that I needed.
Edit:
My apology, I didn't realized that my xml file is fragment xml document and not full XML as per spec.
Given your input file is a malformed XML file that doesn't contain a root node, you can get around this with a bit of string manipulation.
Here's the file you say you have:
<?xml version="1.0" standalone="no" ?>
<WndPos name="FrontEnd.Login" l="703" r="1264" t="323" b="909" />
<LayerManager />
<ViewLayers name="RoofLayout" roof="1" nlwalls="1">
<Layer level="-1" module="1" name="Walls" locked="0" visible="1" />
</ViewLayers>
<DirProfiles>
<ProfileInfo ProfileName="ControlCQFT" JobPath="C:\Jobs" DatabasePath="D:\Database\ControlCQFT" />
</DirProfiles>
<DirHistory>
<ProfileInfo Use="Job" Path="C:\Jobs" />
</DirHistory>
Here's how to work with it:
var sourceFileName = #"C:\{path}\xml_fragments.txt";
var text = $"<root>{String.Join(Environment.NewLine, File.ReadLines(sourceFileName).Skip(1))}</root>";
var doc = XDocument.Parse(text);
doc.Root.Element("DirProfiles").Elements().Remove();
doc.Root.Element("DirProfiles").Add(
new XElement(
"ProfileInfo",
new XAttribute("ProfileName", "Control1"),
new XAttribute("JobPath", #"D:\Client1\JobsA"),
new XAttribute("DatabasePath", #"D:\Database\Control1")));
That gives me:
<root>
<WndPos name="FrontEnd.Login" l="703" r="1264" t="323" b="909" />
<LayerManager />
<ViewLayers name="RoofLayout" roof="1" nlwalls="1">
<Layer level="-1" module="1" name="Walls" locked="0" visible="1" />
</ViewLayers>
<DirProfiles>
<ProfileInfo ProfileName="Control1" JobPath="D:\Client1\JobsA" DatabasePath="D:\Database\Control1" />
</DirProfiles>
<DirHistory>
<ProfileInfo Use="Job" Path="C:\Jobs" />
</DirHistory>
</root>
See following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
XElement doc = new XElement("Root");
doc.Add(XElement.Parse(xml));
XElement dirProfiles = doc.Descendants("DirProfiles").FirstOrDefault();
XElement profileInfo = dirProfiles.Element("ProfileInfo");
profileInfo.SetAttributeValue("ProfileName", "Control1");
profileInfo.SetAttributeValue("JobPath", #"D:\Client1\JobsA");
profileInfo.SetAttributeValue("DatabasePath", #"D:\Database\Control1");
}
}
}
You can parse the XML data to a C# class model, and after that could do the data changes as per requirement. After changes, you can again parse the model object to XML and rewrite the XML string on the same file.
Refer this link for generate a class structure by available XML: https://www.c-sharpcorner.com/blogs/convert-xml-json-file-to-c-sharp-class
And Use this code to Convert Xml to a C# class object
public static T ConvertXmlToObject<T>(String xml)
{
T result = default(T);
try
{
using (TextReader reader = new StringReader(xml))
{
try
{
result =
(T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
catch (InvalidOperationException)
{
// Throw message for invalid XML
}
}
}
catch (Exception ex)
{
}
return result;
}
Call the function like :
var entity = ConvertXmlToObject<ModelClass>(XMLString);
User this code to convert again Object to XML
public static string ConvertObjectToXML<T>(T ModelClass)
{
XmlSerializer xsObject = new XmlSerializer(typeof(T));
var inputObject = ModelClass;
var xmlString = "";
using (var sw = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sw))
{
xsObject.Serialize(writer, inputObject);
xmlString = sw.ToString();
}
}
return xmlString;
}
Call this function like :
string xmlString = ConvertObjectToXML<ModelClass>(ModelClassObject);
what is simplest way to merge two XML file and create new one? I'm using unity and i think it is limited in C# APIs ans references and I'm not professional programmer.
File 1:
<?xml version="1.0" encoding="UTF-8"?>
<UserData>
<Data>
<FIELD1>NAME 1</FIELD1>
</Data>
</UserData>
File 2:
<?xml version="1.0" encoding="UTF-8"?>
<UserData>
<Data>
<FIELD2>NAME 2</FIELD2>
</Data>
</UserData>
Result:
<?xml version="1.0" encoding="UTF-8"?>
<UserData>
<Data>
<FIELD1>NAME 1</FIELD1>
<FIELD2>NAME 2</FIELD2>
</Data>
</UserData>
I'd start with making your implementation of UserData more generic, so that it can accept multiple field types instead of field1 and field2, like:
<?xml version="1.0" encoding="UTF-8"?>
<UserData>
<Data>
<Field>NAME 1</Field>
<Field>NAME 2</Field>
</Data>
</UserData>
Your container could then look like this:
[XmlRoot("UserData")]
public class UserDataContainer
{
public UserDataContainer() {...}
// Can be used load and save a list of strings (Field(s) in XML)
[XmlArray("Data"), XmlArrayItem("Field"),Type = typeof(string))]
public List<string> Data = new List<string>();
public static UserDataContainer Load(path){...}
public void Save(path){...}
public List<string> GetFields(){...}
public void SetFields(List<string> Fields){...}
}
If you need help on loading/writing data specifically you can check out this wiki, it's very well done!
Saving and Loading Data, XmlSerializer
You would load your two UserData files like:
UserDataContainer UserData1 = UserDataContainer.Load(UserData1Path);
UserDataContainer UserData2 = UserDataContainer.Load(UserData2Path);
Later when you want to merge them you could do this:
// Get the contents of the first user data
List<string> CombinedDatas = UserData1.GetFields();
// Combine in the contents of the second user data
// AddRange actually changes the first list (CombinedDatas)
CombinedDatas.AddRange(UserData2.GetFields());
// If you wanted to save out the combined data in a new xml file
UserDataContainer FinalData = new UserDataContainer();
FinalData.SetFields(CombinedDatas);
FinalData.Save(FinalDataPath);
I have an XML Document that stores all sorts of information about users of a system. Utlimately, the nodes that I am intersted in I hae outined below.
So, there is a user that has many user contents - I have included just books as an example.
<?xml version="1.0" encoding="UTF-8"?>
<user>
<userProperties>
<alias val="userAliasOne"/>
<id val="3423423"/>
</userProperties>
<userContent>
<userBooks>
<genre>
<book>
<title>Dummy Value</title>
</book>
</genre>
</userBooks>
</userContent>
</user>
I need to somehow restructure the XML, using XmlDocument and XmlNode so that it matches the below. (userBooks to become root node but all contents of userBooks - /genre/book/title - to stay inside userContent).
<?xml version="1.0" encoding="UTF-8"?>
<userBooks>
<user>
<userProperties>
<alias val="userAliasOne"/>
<id val="3423423"/>
</userProperties>
<userContent>
<genre>
<book>
<title>Dummy Value</title>
</book>
</genre>
</userContent>
</user>
</userBooks>
I've tried selecting the single nodes and cloning them, then appending the clone to the parent and removing the child that's no longer required. It became very long and convoluted and I couldn't get it to work. There must be a more elegant solution that I am not aware of.
Any help appreciated.
Thanks.
Using XML Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<XElement> userBooks = doc.Descendants("userBooks").ToList();
foreach(XElement userBook in userBooks)
{
userBook.ReplaceWith(userBook.Element("genre"));
}
}
}
}
Here's an example for adding a new root element:
using System;
using System.Xml;
class Test
{
static void Main()
{
XmlDocument doc = new XmlDocument();
doc.Load("test.xml");
var originalRoot = doc.DocumentElement;
doc.RemoveChild(originalRoot);
var newRoot = doc.CreateElement("userBooks");
doc.AppendChild(newRoot);
newRoot.AppendChild(originalRoot);
doc.Save(Console.Out);
}
}
Try using the same approach for "removing" the userBooks element in the original - remove the element from its parent, but then add all the child nodes (of userBooks) as new child nodes of the original parent of userBooks.
Hello and today I want to find out how I can read an xml file in the following way, I have not been able to find ANYTHING like this or anythig simulaur to how I want to do this that works. I have an xml file with the following content format that has been disabled below this.
<smallusers>
<user id="1">
<name>John</name>
<motto>I am john, who are you?</motto>
</user>
<user id="2">
<name>Peter</name>
<motto>Hello everyone!</motto>
</user>
</smallusers>
<bigusers>
<user id="3">
<name>Barry</name>
<motto>Earth is awesome</motto>
</user>
</bigusers>
How can I put that into 2 string lists in csharp
Load it as a text file into a string or StringBuilder.
prefix it with <xml> and end it with </xml>
then use XmlDocument to load your xml
XML can have only one root tag. You input has more than one root. So you have to wrap your XML in a root like code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.txt";
static void Main(string[] args)
{
string input = File.ReadAllText(FILENAME);
input = string.Format("<Root>{0}</Root>", input);
XElement root = XElement.Parse(input);
}
}
}