I have many XMLs that I want to flatten out and save as a file (as below)using C#. One option that I tried is to use excel to import the file and then call the vba script from c#. Is there any option to do this in C#.
Sample input xml:
<request>
<log-date>11/28/2016 04:48:40</log-date>
<service-name>getPdf</service-name>
<request-id>1234</request-id>
<request-xml>
<MyRequest xmlns="http://abcd.com">
<GroupID>123</GroupID>
<ClientName>ACBD</ClientName>
<BrokerInfo>
<BrokerLoginName>9876</BrokerLoginName>
<FullName>John</FullName>
</BrokerInfo>
<BrokerInfo>
<BrokerLoginName>0987</BrokerLoginName>
<FullName>Mike</FullName>
</BrokerInfo>
</MyRequestRequest>
</request-xml>
</request>
Expected output file:
log-date|service-name|request-id|groupID|ClientName|BrokerLoginName|FullName
11/28/2016 04:48:40|getPdf|1234|123|ACBD|9876|John
11/28/2016 04:48:40|getPdf|1234|123|ACBD|0987|Mike
Here is your solution:
using System.IO;
using System.Xml;
public static void ReadInnerText()
{
StreamWriter file = new StreamWriter("myTextFile.txt");
file.WriteLine("log-date|service-name|request-id|groupID|ClientName|BrokerLoginName|FullName");
string Line = string.Empty;
string BrokerLoginName = string.Empty;
XmlDocument doc = new XmlDocument();
XmlNodeList SecondTag;
XmlNodeList ThirdTag;
XmlNodeList FourthTag;
XmlNodeList FifthTag;
doc.Load("inputFile.xml");
XmlNodeList elemList = doc.GetElementsByTagName("request");
foreach (XmlNode firstNode in elemList)
{
SecondTag = firstNode.ChildNodes;
foreach (XmlNode SecondNode in SecondTag)
{
if (SecondNode.Name.Equals("log-date"))
{
Line = SecondNode.InnerText + "|";
}
if (SecondNode.Name.Equals("service-name"))
{
Line = Line + SecondNode.InnerText + "|";
}
if (SecondNode.Name.Equals("request-id"))
{
Line = Line + SecondNode.InnerText + "|";
}
ThirdTag = SecondNode.ChildNodes;
foreach (XmlNode ThirdNode in ThirdTag)
{
FourthTag = ThirdNode.ChildNodes;
foreach (XmlNode FourthNode in FourthTag)
{
if (FourthNode.Name.Equals("GroupID"))
{
Line = Line + FourthNode.InnerText + "|";
}
if (FourthNode.Name.Equals("GroupName"))
{
Line = Line + FourthNode.InnerText + "|";
}
if (FourthNode.Name.Equals("ClientName"))
{
Line = Line + FourthNode.InnerText + "|";
}
FifthTag = FourthNode.ChildNodes;
foreach (XmlNode FifthNode in FifthTag)
{
if (FifthNode.Name.Equals("BrokerLoginName"))
{
BrokerLoginName = FifthNode.InnerText + "|";
}
if (FifthNode.Name.Equals("FullName"))
{
file.WriteLine(Line+BrokerLoginName+FifthNode.InnerText);
}
}
}
}
}
}
file.Close();
}
Related
I am beginner in programming. I have a scenario like this:
For each unique application member, I want to return a new XML that contains for each EMPLOYEE_MEMBER_INDIVID all concatenated values of EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION field.
Roles should be concatenated for each MEMBER_UNIQID from APPLICATION_MEMBER nodes.
<EMPLOYEE_MEMBER_INDIVID>
<EMPLOYEE_MEMBER_INDIVID_MAIN_DATA ENTITY="">
<EMPLOYEE_MEMBER_INDIVID_UNIQ_ID>096788</EMPLOYEE_MEMBER_INDIVID_UNIQ_ID>
<EMPLOYEE_MEMBER_INDIVID_NAME>Dina</EMPLOYEE_MEMBER_INDIVID_NAME>
<EMPLOYEE_MEMBER_INDIVID_SURNAME>Gomez</EMPLOYEE_MEMBER_INDIVID_SURNAME>
</EMPLOYEE_MEMBER_INDIVID_MAIN_DATA>
<EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S>
<EMPLOYEE_MEMBER_INDIVID_ROLE_DATA ENTITY="">
<EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION>Co-borrower</EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION>
</EMPLOYEE_MEMBER_INDIVID_ROLE_DATA>
<EMPLOYEE_MEMBER_INDIVID_ROLE_DATA ENTITY=""> <EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION>Guarantor</EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION>
</EMPLOYEE_MEMBER_INDIVID_ROLE_DATA>
<EMPLOYEE_MEMBER_INDIVID_ROLE_DATA ENTITY="">
<EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION>Mortgager individual</EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION>
</EMPLOYEE_MEMBER_INDIVID_ROLE_DATA>
</EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S>
</EMPLOYEE_MEMBER_INDIVID>
The output node should be:
<EMPLOYEE_MEMBER_INDIVID>
<EMPLOYEE_MEMBER_INDIVID_MAIN_DATA ENTITY="">
<EMPLOYEE_MEMBER_INDIVID_UNIQ_ID>096788</EMPLOYEE_MEMBER_INDIVID_UNIQ_ID>
<EMPLOYEE_MEMBER_INDIVID_NAME>Dina</EMPLOYEE_MEMBER_INDIVID_NAME>
<EMPLOYEE_MEMBER_INDIVID_SURNAME>Gomez</EMPLOYEE_MEMBER_INDIVID_SURNAME>
</EMPLOYEE_MEMBER_INDIVID_MAIN_DATA>
<EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S>
<EMPLOYEE_MEMBER_INDIVID_ROLE_DATA ENTITY="">
<EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION>Co-borrower / Guarantor / Mortgager individual</EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION>
</EMPLOYEE_MEMBER_INDIVID_ROLE_DATA>
</EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S>
</EMPLOYEE_MEMBER_INDIVID>
My code is:
static void Main(string[] args)
{
try
{
//Create A XML Document Of Response String
XmlDocument xmlDoc = new XmlDocument();
//Read the XML File
XmlNodeList nodeList2 = xmlDoc.SelectNodes("//EMPLOYEE_MEMBER_S/EMPLOYEE_MEMBER" +
"[(EMPLOYEE_MEMBER_INDIVID/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA/EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION ='Borrower' " +
"or EMPLOYEE_MEMBER_INDIVID/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA/EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION='Mortgager' " +
"or EMPLOYEE_MEMBER_INDIVID/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA/EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION='Co-borrower')]");
List<string> baseMemberUNIQ_IDs = new List<string>();
List<LoanMember> infos = new List<LoanMember>();
XmlNodeList baseMembersList = xmlDoc.SelectNodes("//APPLICATION_MEMBERS/APPLICATION_MEMBER[ROLE='Borrower' or ROLE='Mortgager individual' or ROLE='Co-borrower']");
foreach (XmlNode xmlNode in baseMembersList)
{
baseMemberUNIQ_IDs.Add(xmlNode["MEMBER_UNIQ_ID"].InnerText);
}
var distinctBaseMembersUNIQ_ID = baseMemberUNIQ_IDs.Distinct();
foreach (var UNIQ_ID in distinctBaseMembersUNIQ_ID)
{
XmlNodeList nodeList = xmlDoc.SelectNodes("//EMPLOYEE_MEMBER_S/EMPLOYEE_MEMBER" +
"[(EMPLOYEE_MEMBER_INDIVID/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA/EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION ='Borrower' " +
"or EMPLOYEE_MEMBER_INDIVID/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA/EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION='Mortgager individual' " +
"or EMPLOYEE_MEMBER_INDIVID/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S/EMPLOYEE_MEMBER_INDIVID_ROLE_DATA/EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION='Co-borrower') " +
"and EMPLOYEE_MEMBER_INDIVID/EMPLOYEE_MEMBER_INDIVID_MAIN_DATA/EMPLOYEE_MEMBER_INDIVID_UNIQ_ID=" + UNIQ_ID.ToString() + "]");
foreach (XmlNode xmlNode2 in nodeList)
{
String ROLE = "";
foreach (XmlNode childNode in xmlNode2)
{
ROLE = childNode.ChildNodes[0].InnerXml;
Console.WriteLine("CONCATED ROLES ARE " + ROLE);
// All roles of each employee individ should be concatenated inside the first node EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION node, Other nodes shoud be removed/
}
}
}
}
catch
{
throw;
}
Console.ReadKey();
}
}
In the following url is input document XML: https://codebeautify.org/xmlviewer/cb7a26e5
Thank you for your help!
Try following 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> EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S = doc.Descendants("EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S").ToList();
foreach (XElement EMPLOYEE_MEMBER_INDIVID_ROLE_DATA in EMPLOYEE_MEMBER_INDIVID_ROLE_DATA_S)
{
string[] roles = EMPLOYEE_MEMBER_INDIVID_ROLE_DATA.Descendants("EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION").Select(x => (string)x).ToArray();
XElement newEMPLOYEE_MEMBER_INDIVID_ROLE_DATA = new XElement("EMPLOYEE_MEMBER_INDIVID_ROLE_DATA", new object[] {
new XAttribute("ENTITY", ""),
new XElement("EMPLOYEE_MEMBER_INDIVID_ROLE_ON_APPLICATION", string.Join(" / ", roles))
});
EMPLOYEE_MEMBER_INDIVID_ROLE_DATA.ReplaceWith(newEMPLOYEE_MEMBER_INDIVID_ROLE_DATA);
}
}
}
}
I'm almost getting there, but I need some help.
This is the code that I use to process our XML file. I'm able to find the section that I need to store; I just don't know how to save it.
XmlDocument doc = new XmlDocument();
doc.XmlResolver = null;
doc.Load(#"c:\xml\Sales.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("nd/ni/nv/noid");
foreach (XmlNode node in nodes)
{
if (node.OuterXml.IndexOf("Server=1,Function=1,Location=") > 0)
{
Console.WriteLine(node.OuterXml);
// This prints out "<noid>Server=1,Function=1,Location=24</noid>"
// How do I read the four <r> nodes within this <noid>?
// The values would be [124, 2, 43, 90]
}
}
The xml looks something like this:
<nd>
<ni>
<nv>
<noid>Managed=1,Network=1,smtp=1</noid>
<r>27</r>
<r>4</r>
</nv>
<nv>
<noid>Managed=1,Network=1,Ibc=1</noid>
<r>8</r>
<r>2</r>
</nv>
<nv>
<noid>Server=1,Function=1,Location=24</noid>
<r>124</r>
<r>2</r>
<r>43</r>
<r>90</r>
</nv>
<nv>
<noid>Unmanaged=9,Label=7,Place=5</noid>
<r>10</r>
<r>20</r>
</nv>
</ni>
</nd>
Console.WriteLine prints the correct <noid> text, so I know that I've already found the section with the relevant data.
My question is, how can I read the four <r> inside this <noid>? Ideally, within the IF statement, how can I read all the <r> elements that are between the <nv></nv>?
Thanks.
Using Linq-to-xml
var xmlText = File.ReadAllText(#"C:\YourDirectory\YourFile.xml");
var xDoc = XDocument.Parse(xmlText);
var rValues = new List<string>(); //THIS IS YOUR RESULT
var nvNodes = xDoc.Descendants("nv");
foreach(var el in nvNodes)
{
if (el.Element("noid").Value.Contains("Server=1,Function=1,Location="))
rValues = el.Elements("r").Select(e => e.Value).ToList();
}
Or, replacing the foreach with Linq (fails if First() is not satisfied)
var rValues = nvNodes.
First(nv => nv.Value.Contains("Server=1,Function=1,Location="))
.Elements("r")
.Select(r => r.Value);
A non-optimized, non-linq solution
XmlDocument doc = new XmlDocument();
doc.XmlResolver = null;
doc.Load(#"C:\YourDirectory\YourFile.xml");
var rValues = new List<string>(); //THIS IS YOUR RESULT
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("//nd/ni/nv");
foreach (XmlNode node in nodes)
{
if (node.FirstChild.InnerText.Contains("Server=1,Function=1,Location="))
{
foreach(XmlNode childnode in node.ChildNodes)
{
if (childnode.Name == "r")
rValues.Add(childnode.InnerText);
}
}
}
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string input =
"<nd>" +
"<ni>" +
"<nv>" +
"<noid>Managed=1,Network=1,smtp=1</noid>" +
"<r>27</r>" +
"<r>4</r>" +
"</nv>" +
"<nv>" +
"<noid>Managed=1,Network=1,Ibc=1</noid>" +
"<r>8</r>" +
"<r>2</r>" +
"</nv>" +
"<nv>" +
"<noid>Server=1,Function=1,Location=24</noid>" +
"<r>124</r>" +
"<r>2</r>" +
"<r>43</r>" +
"<r>90</r>" +
"</nv>" +
"<nv>" +
"<noid>Unmanaged=9,Label=7,Place=5</noid>" +
"<r>10</r>" +
"<r>20</r>" +
"</nv>" +
"</ni>" +
"</nd>";
XElement nd = XElement.Parse(input);
var results = nd.Descendants("nv").Select(x => new
{
noid = (string)x.Element("noid"),
r = x.Elements("r").Select(y => (int)y).ToList()
}).ToList();
}
}
}
A short, but difficult to understand XPath expression:
XmlNodeList rNodes = root.SelectNodes(
"nd/ni/nv[noid/text()[contains(.,'Server=1,Function=1,Location=')]]/r");
foreach (XmlNode rNode in rNodes)
Console.WriteLine(rNode.InnerText);
I am looking for the best way to compare XML data with a string.
the data is stored in a xml called test.xml, and must be compared with the name descendant, if there is a match more info from the xml must be added to a textbox and picture box.
My ( working ) code:
var xmlDocument = XDocument.Load("test.xml"); // XML koppellen
var key1 = xmlDocument.Descendants("NAME"); // XML filepath
var key2 = xmlDocument.Descendants("TITLE"); // XML titel
var key3 = xmlDocument.Descendants("BRAND"); // XML afbeelding
var key4 = xmlDocument.Descendants("TYPE"); // XML merk
var key5 = xmlDocument.Descendants("SOORT"); // XML type
var key6 = xmlDocument.Descendants("NAAM"); // XML naam
List<string> file = new List<string>();
List<string> title = new List<string>();
List<string> brand = new List<string>();
List<string> type = new List<string>();
List<string> soort = new List<string>();
List<string> naam = new List<string>();
int i = 0;
foreach (var key in key1)
{
file.Add(key.Value.Trim());
}
foreach (var key in key2)
{
title.Add(key.Value.Trim());
}
foreach (var key in key3)
{
brand.Add(key.Value.Trim());
}
foreach (var key in key4)
{
type.Add(key.Value.Trim());
}
foreach (var key in key5)
{
soort.Add(key.Value.Trim());
}
foreach (var key in key6)
{
naam.Add(key.Value.Trim());
}
foreach (var Name in naam)
{
if (textBox3.Text.ToString() == Name.ToString())
{
PDFLocation = file[i].ToString();
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
title[i].ToString() + "\r\n" +
brand[i].ToString() + "\r\n" +
type[i].ToString() + "\r\n" +
soort[i].ToString() + "\r\n" +
textBox3.Text + "\r\n";
}
i++;
}
]
I think this is not the best way to do it, but cant see a better way....
Update: solution:
foreach (XElement element in xmlDocument.Descendants("PDFDATA"))
{
if (textBox3.Text.ToString() == element.Element("NAAM").Value.Trim())
{
PDFLocation = element.Element("NAME").Value.ToString();
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
element.Element("TITLE").Value + "\r\n" +
element.Element("BRAND").Value + "\r\n";
break;
}
}
Instead of thinking of the xml and a bunch of individual lists of data, it helps to think of it more as objects. Then you can loop through each element one at a time and don't need to split it up into individual lists. This not only removes duplicate code but more importantly creates a better abstraction of the data you are working with. This makes it easier to read and understand what the code is doing.
foreach (XElement element in xmlDocument.Elements())
{
if (textBox3.Text.ToString() == element.Element("NAAM").Value)
{
PDFLocation = element.Element("NAAM").Value;
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
element.Element("Title").Value + "\r\n" +
element.Element("Brand").Value + "\r\n" +
element.Element("Type").Value + "\r\n"
// access rest of properties...
}
}
I have an XML file which have multiple messages in one large file, my objective it to split the file into singe xml file for each message, I have a c# code which only gets me the first instance of the message. can you please tell what am I missing here:
Here is my code :
string strSeq;
string strFileName;
XDocument doc = XDocument.Load(#"C:\XMl\MR.xml");
var newDocs = doc.Descendants("Message")
.Select(d => new XDocument(new XElement("FileDump", d)));
foreach (var newDoc in newDocs)
{
strSeq = XDocument.Load(#"C:\XMl\MR.xml").XPathSelectElement
"//FileDump/Message/MsgID").Value;
strFileName = "MR_" + strSeq + ".xml";
newDoc.Save(Console.Out); Console.WriteLine();
newDoc.Save(#"C:\xml\MR\Tst\" + strFileName);
Console.WriteLine();
}
You should search for message ID within newDoc instead of doc:
foreach (var newDoc in newDocs)
{
strSeq = newDoc.XPathSelectElement("//FileDump/Message/MsgID").Value;
strFileName = "MR_" + strSeq + ".xml";
newDoc.Save(Console.Out); Console.WriteLine();
newDoc.Save(#"C:\xml\MR\Tst\" + strFileName);
Console.WriteLine();
}
Try,
string path = #"C:\xml\MR\Tst\MR_";
XElement root = XElement.Load(file);
foreach(XElement message in root.Descendants("Message"))
{
string id = message.Element("MsgID").Value;
message.Save(path + id + ".xml");
}
I have created a small XML tool which gives me count of specific XML tags from multiple XML files.
The code for this is as follow:
public void SearchMultipleTags()
{
if (txtSearchTag.Text != "")
{
try
{
//string str = null;
//XmlNodeList nodelist;
string folderPath = textBox2.Text;
DirectoryInfo di = new DirectoryInfo(folderPath);
FileInfo[] rgFiles = di.GetFiles("*.xml");
foreach (FileInfo fi in rgFiles)
{
int i = 0;
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(fi.FullName);
//rtbox2.Text = fi.FullName.ToString();
foreach (XmlNode node in xmldoc.GetElementsByTagName(txtSearchTag.Text))
{
i = i + 1;
//
}
if (i > 0)
{
rtbox2.Text += DateTime.Now + "\n" + fi.FullName + " \nInstance: " + i.ToString() + "\n\n";
}
else
{
//MessageBox.Show("No Markup Found.");
}
//rtbox2.Text += fi.FullName + "instances: " + str.ToString();
}
}
catch (Exception)
{
MessageBox.Show("Invalid Path or Empty File name field.");
}
}
else
{
MessageBox.Show("Dont leave field blanks.");
}
}
This code returns me the tag counts in Multiple XML files which user wants.
Now the same I want to Search for particular text and its count present in XML files.
Can you suggest the code using XML classes.
Thanks and Regards,
Mayur Alaspure
Use LINQ2XML instead..It's simple and a complete replacement to othe XML API's
XElement doc = XElement.Load(fi.FullName);
//count of specific XML tags
int XmlTagCount=doc.Descendants().Elements(txtSearchTag.Text).Count();
//count particular text
int particularTextCount=doc.Descendants().Elements().Where(x=>x.Value=="text2search").Count();
System.Xml.XPath.
Xpath supports counting: count(//nodeName)
If you want to count nodes with specific text, try count(//*[text()='Hello'])
See How to get count number of SelectedNode with XPath in C#?
By the way, your function should probably look something more like this:
private int SearchMultipleTags(string searchTerm, string folderPath) { ...
//...
return i;
}
Try using XPath:
//var document = new XmlDocument();
int count = 0;
var nodes = document.SelectNodes(String.Format(#"//*[text()='{0}']", searchTxt));
if (nodes != null)
count = nodes.Count;