Below is the XML sample. 'file' is the repeated node. Need to read 'filename' and 'sftp1' ,'sftp2','sftp3' elements values from 'sftp'. we need to repeat the same for each 'file' Node.
<FTPLocations>
<file>
<filedetails>
<filename>sample.txt</filename>
</filedetails>
<sftp>
<sftp1>
<sftp-username>UN</sftp-username>
<sftp-password>PW</sftp-password>
<sftp-host>ipaddress</sftp-host>
<sftp-path>path</sftp-path>
</sftp1>
<sftp2>
<sftp-username>UN</sftp-username>
<sftp-password>PW</sftp-password>
<sftp-host>ipaddress</sftp-host>
<sftp-path>path</sftp-path>
</sftp2>
<sftp3>
<sftp-username>UN</sftp-username>
<sftp-password>PW</sftp-password>
<sftp-host>ipaddress</sftp-host>
<sftp-path>path</sftp-path>
</sftp3>
</sftp>
</file>
<file>
<filedetails>
<filename>sample.txt</filename>
</filedetails>
<sftp>
<sftp1>
<sftp-username>UN</sftp-username>
<sftp-password>PW</sftp-password>
<sftp-host>ipaddress</sftp-host>
<sftp-path>path</sftp-path>
</sftp1>
<sftp2>
<sftp-username>UN</sftp-username>
<sftp-password>PW</sftp-password>
<sftp-host>ipaddress</sftp-host>
<sftp-path>path</sftp-path>
</sftp2>
<sftp3>
<sftp-username>UN</sftp-username>
<sftp-password>PW</sftp-password>
<sftp-host>ipaddress</sftp-host>
<sftp-path>path</sftp-path>
</sftp3>
</sftp>
</file>
</FTPLocations>
Please suggest me how I can achieve this using C#.
You can access elements of your XML using following code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("YOUR_PATH_TO_XML");
//for sftp1
XmlNodeList sftp1_hd = xmlDoc.GetElementsByTagName("sftp1");
foreach (XmlNode sftp1_node in sftp1_hd)
{
foreach (XmlNode sftp1_child_nodes in sftp1_node.ChildNodes)
{
Console.WriteLine(sftp1_child_nodes.LocalName);
Console.WriteLine(sftp1_child_nodes.InnerText);
}
}
//for sftp2
XmlNodeList sftp2_hd = xmlDoc.GetElementsByTagName("sftp2");
foreach (XmlNode sftp2_node in sftp2_hd)
{
foreach (XmlNode sftp2_child_nodes in sftp2_node.ChildNodes)
{
Console.WriteLine(sftp2_child_nodes.LocalName);
Console.WriteLine(sftp2_child_nodes.InnerText);
}
}
Try xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication47
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("sftp").Elements().Select(x => new
{
name = x.Name.LocalName,
username = (string)x.Element("sftp-username"),
password = (string)x.Element("sftp-password"),
host = (string)x.Element("sftp-ipaddress"),
path = (string)x.Element("sftp-path")
}).ToList();
}
}
}
Related
I have been on google for a while but am just stumped. I need to parse xml of this nature. I can't seem to skip to elements in the middle, e.g. Folder. I have limited the xml as there were many 'Folder' elements. Any guidance would be appreciated. I was after the FolderID element's attribute ID.
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:ServerVersionInfo MajorVersion="14"
MinorVersion="1"
MajorBuildNumber="225"
MinorBuildNumber="46"
Version="Exchange2010_SP1"
xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<m:GetFolderResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:GetFolderResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Folders>
<t:Folder>
<t:FolderId Id="AAMkADk5MmY1ZThmLTM2MzAtNGVh" ChangeKey="AQAAABYAAACSe/NBrSZiQKqHx8yL+lIRAAAA1EWM" />
<t:ParentFolderId Id="AAMkADk5MmY1ZThmLTM2MzAtNGVh" ChangeKey="AQAAAA==" />
<t:DisplayName>Top of Information Store</t:DisplayName>
<t:TotalCount>0</t:TotalCount>
<t:ChildFolderCount>15</t:ChildFolderCount>
<t:EffectiveRights>
<t:CreateAssociated>true</t:CreateAssociated>
<t:CreateContents>true</t:CreateContents>
<t:CreateHierarchy>true</t:CreateHierarchy>
<t:Delete>true</t:Delete>
<t:Modify>true</t:Modify>
<t:Read>true</t:Read>
<t:ViewPrivateItems>true</t:ViewPrivateItems>
</t:EffectiveRights>
<t:PermissionSet>
<t:Permissions>
<t:Permission>
<t:UserId>
<t:DistinguishedUser>Default</t:DistinguishedUser>
</t:UserId>
<t:CanCreateItems>false</t:CanCreateItems>
<t:CanCreateSubFolders>false</t:CanCreateSubFolders>
<t:IsFolderOwner>false</t:IsFolderOwner>
<t:IsFolderVisible>false</t:IsFolderVisible>
<t:IsFolderContact>false</t:IsFolderContact>
<t:EditItems>None</t:EditItems>
<t:DeleteItems>None</t:DeleteItems>
<t:ReadItems>None</t:ReadItems>
<t:PermissionLevel>None</t:PermissionLevel>
</t:Permission>
<t:Permission>
<t:UserId>
<t:DistinguishedUser>Anonymous</t:DistinguishedUser>
</t:UserId>
<t:CanCreateItems>false</t:CanCreateItems>
<t:CanCreateSubFolders>false</t:CanCreateSubFolders>
<t:IsFolderOwner>false</t:IsFolderOwner>
<t:IsFolderVisible>false</t:IsFolderVisible>
<t:IsFolderContact>false</t:IsFolderContact>
<t:EditItems>None</t:EditItems>
<t:DeleteItems>None</t:DeleteItems>
<t:ReadItems>None</t:ReadItems>
<t:PermissionLevel>None</t:PermissionLevel>
</t:Permission>
</t:Permissions>
</t:PermissionSet>
<t:UnreadCount>0</t:UnreadCount>
</t:Folder>
</m:Folders>
</m:GetFolderResponseMessage>
</m:ResponseMessages>
</m:GetFolderResponse>
</s:Body>
</s:Envelope>
LINQ to XML is the best .NET XML Parsing API.
See
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/xdocument-class-overview
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace ConsoleApp12
{
class Program
{
static void Main(string[] args)
{
var doc = XDocument.Load(#"c:\temp\foo.xml");
var ns = (XNamespace)"http://schemas.microsoft.com/exchange/services/2006/types";
var folders = doc.Descendants(ns + "Folder");
foreach (var e in folders)
{
var folderId = e.Element(ns + "FolderId").Attribute("Id").Value;
Console.WriteLine(folderId);
}
Console.WriteLine("Hit any key to exit.");
Console.ReadKey();
}
}
}
You should learn about serlialization. It's very easy to convert an XML to and from a object in C#. https://www.codeproject.com/Articles/483055/XML-Serialization-and-Deserialization-Part
That said, this will get you the data you're after. It's not very reusable and won't help you with any xml files other than ones with one instance of that attribute, but it's what you're after so here you go.
string FolderId;
string ChangeKey;
using (StreamReader sr = new StreamReader("c:\\myfile.xml"))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.Contains("<t:FolderId Id="))
{
try
{
var lineArray = line.Split('\"');
FolderId = lineArray[1];
ChangeKey = lineArray[3];
}
catch
{
// handle exception
}
}
}
}
You can use the XSD.exe to create a schema class. and then using XML deserializer, you can deserialize/parse xml to object
Using xml linq
XDocument doc = XDocument.Load(FILENAME);
List<XElement> folders = doc.Descendants().Where(x => x.Name.LocalName == "Folder").ToList();
XNamespace tNs = folders.FirstOrDefault().GetNamespaceOfPrefix("t");
XElement id_AAMkADk5MmY1ZThmLTM2MzAtNGVh = folders.Where(x => (string)x.Element(tNs + "FolderId").Attribute("Id") == "AAMkADk5MmY1ZThmLTM2MzAtNGVh").FirstOrDefault();
How to parse all the XML files under a given directory as an input to the application and write its output to a text file.
Note: The XML is not always the same the nodes in the XML can vary and have any number of Child-nodes.
Any help or guidance would be really helpful on this regard :)
XML File Sample
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>
<CNT>USA</CNT>
<CODE>3456</CODE>
</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
</CATALOG>
C# Code
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace XMLTagParser
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please Enter the Location of the file");
// get the location we want to get the sitemaps from
string dirLoc = Console.ReadLine();
// get all the sitemaps
string[] sitemaps = Directory.GetFiles(dirLoc);
StreamWriter sw = new StreamWriter(Application.StartupPath + #"\locs.txt", true);
// loop through each file
foreach (string sitemap in sitemaps)
{
try
{
// new xdoc instance
XmlDocument xDoc = new XmlDocument();
//load up the xml from the location
xDoc.Load(sitemap);
// cycle through each child noed
foreach (XmlNode node in xDoc.DocumentElement.ChildNodes)
{
// first node is the url ... have to go to nexted loc node
foreach (XmlNode locNode in node)
{
string loc = locNode.Name;
// write it to the console so you can see its working
Console.WriteLine(loc + Environment.NewLine);
// write it to the file
sw.Write(loc + Environment.NewLine);
}
}
}
catch {
Console.WriteLine("Error :-(");
}
}
Console.WriteLine("All Done :-)");
Console.ReadLine();
}
}
}
Preferred Output:
CATALOG/CD/TITLE
CATALOG/CD/ARTIST
CATALOG/CD/COUNTRY/CNT
CATALOG/CD/COUNTRY/CODE
CATALOG/CD/COMPANY
CATALOG/CD/PRICE
CATALOG/CD/YEAR
CATALOG/CD/TITLE
CATALOG/CD/ARTIST
CATALOG/CD/COUNTRY
CATALOG/CD/COMPANY
CATALOG/CD/PRICE
CATALOG/CD/YEAR
This is a recursive problem, and what you are looking for is called 'tree traversal'. What this means is that for each child node, you want to look into it's children, then into that node's children (if it has any) and so on, recording the 'path' as you go along, but only printing out the names of the 'leaf' nodes.
You will need a function like this to 'traverse' the tree:
static void traverse(XmlNodeList nodes, string parentPath)
{
foreach (XmlNode node in nodes)
{
string thisPath = parentPath;
if (node.NodeType != XmlNodeType.Text)
{
//Prevent adding "#text" at the end of every chain
thisPath += "/" + node.Name;
}
if (!node.HasChildNodes)
{
//Only print out this path if it is at the end of a chain
Console.WriteLine(thisPath);
}
//Look into the child nodes using this function recursively
traverse(node.ChildNodes, thisPath);
}
}
And then here is how I would add it into your program (within your foreach sitemap loop):
try
{
// new xdoc instance
XmlDocument xDoc = new XmlDocument();
//load up the xml from the location
xDoc.Load(sitemap);
// start traversing from the children of the root node
var rootNode = xDoc.FirstChild;
traverse(rootNode.ChildNodes, rootNode.Name);
}
catch
{
Console.WriteLine("Error :-(");
}
I made use of this other helpful answer: Traverse a XML using Recursive function
Hope this helps! :)
my xml file is like below:
<?xml version="1.0"?>
<UpdateInboundim613Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" status="SUCCESS" message="Success" schemaRevisionDate="2016-07-19" schemaRevisionLevel="0" returnCode="0" xmlns="http://schemas.hp.com/SM/7">
<model>
<keys>
<TransactionID type="String">E-InHPSXIM1089779</TransactionID>
</keys>
<instance uniquequery="TransactionID="E-InHPSXIM1089779"" recordid="E-InHPSXIM1089779">
<TransactionDetailedTrace xsi:nil="true" />
<TransactionMessage type="Array">
<TransactionMessage type="String" />
</TransactionMessage>
<OVSCSolutionDescription type="Array">
<OVSCSolutionDescription type="String">Issue: EL-BANK OUTSIDE WAREHOUSE EGYPT IMEA[2702]Interface[[E1 0/0/0]]|Router|ELBKCE1GW /pg-h-pg1252-256675160|143.34.213.18|Down Solution: As per update from Mai Shrief that the site has been suspended on 30th June. So no need of any investigation. Resolved By: BT NOC</OVSCSolutionDescription>
</OVSCSolutionDescription>
<OVSCTicketID type="String">E-IM004004076</OVSCTicketID>
<RIMSImpact xsi:nil="true" />
<attachments />
</instance>
</model>
<messages>
<message type="String" xmlns="http://schemas.hp.com/SM/7/Common">TransactionStatusDetail in $L.file is:IM Ticket: E-IM004004076 is valid for Update Subtype: Resolve</message>
</messages>
</UpdateInboundim613Response>
but my code cannot get value of element "OVSCTicketID":
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\zzx\Project\SM\R5.1\Harness\InBound.xml");
XmlNode sigNode = xmlDoc.SelectSingleNode("/UpdateInboundim613Response/model/instance/OVSCTicketID");
if (sigNode != null)
{
Console.WriteLine(sigNode.InnerText);
}
can you please tell me what's the problem and how to fix it?
Your Xml document uses the default namespace "http://schemas.hp.com/SM/7". You need to use the XmlNamespaceManager to select that node under this namespace.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\zzx\Project\SM\R5.1\Harness\InBound.xml");
var namespaceManager = new XmlNamespaceManager(xmlDoc.NameTable);
namespaceManager.AddNamespace("ns", "http://schemas.hp.com/SM/7");
XmlNode sigNode = xmlDoc.SelectSingleNode("//ns:UpdateInboundim613Response//ns:model//ns:instance//ns:OVSCTicketID",namespaceManager);
if (sigNode != null)
{
Console.WriteLine(sigNode.InnerText);
}
Above code should work fine.
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);
XNamespace defaultNs = ((XElement)doc.FirstNode).GetDefaultNamespace();
string ovsCTicketID = (string)doc.Descendants(defaultNs + "OVSCTicketID").FirstOrDefault();
}
}
}
I have xml fragment in an xml-File. The fragment has tags with namespace.
How can I read that xml fragment, which represent exactly an XElement element ?
<node id="n0::n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="91.44" width="59.49119999999999" x="364.256180835285" y="-698.4404365079365"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="48.677734375" x="5.406732812499968" y="4.0">MELEIN</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="27.35546875" x="16.067865624999968" y="20.843814062500087">8,00<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="-0.5" nodeRatioX="0.0" nodeRatioY="-0.2720492775317138" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
I tried a lot of different ways the last one nearly comes to the target
var mngr = new System.Xml.XmlNamespaceManager(new System.Xml.NameTable());
mngr.AddNamespace(string.Empty, "urn: ignore"); // or proper URL
mngr.AddNamespace("y", "urn:ignore"); // or proper URL
var parserContext = new System.Xml.XmlParserContext(null, mngr, null, System.Xml.XmlSpace.None, null);
var txtReader = new System.Xml.XmlTextReader("block.graphml", System.Xml.XmlNodeType.Element, parserContext);
var ele = XElement.Load(txtReader);
but it crashes in the last line with System.InvalidOperationException
Is there any easy way to import xml fragment to an existing xelement?
I would prefer the way XElement.load("block.graphml"); This didn't work at all.
Thanks for your tips
You can do it like this
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);
XElement element = XElement.Parse("<Root xmlns:y=\"www.mynamespace.com\"></Root>");
element.Add(input);
}
}
}
I have a Java generated (List Collection) XML format of:
<java.util.Collections>
<org.yccheok.jstock.engine.Stock>
<code>
<code> RBS.L</code>
</code>
<symbol>
<symbol> ROYAL BK SCOTL GR</symbol>
</symbol>
<name> ROYAL BK SCOTL GR</name>
<board> London</board>
<industry> Unknown</industry>
<prevPrice> 23.74</prevPrice>
<openPrice> 23.41</openPrice>
<lastPrice> 24.4</lastPrice>
<highPrice> 24.855</highPrice>
<lowPrice> 23.0</lowPrice>
<volume> 51353968</volume>
<changePrice> 0.66</changePrice>
<changePricePercentage> 2.78</changePricePercentage>
<lastVolume> 795</lastVolume>
<buyPrice> 24.39</buyPrice>
<buyQuantity> 51203</buyQuantity>
<sellPrice> 24.4</sellPrice>
<sellQuantity> 370763</sellQuantity>
<secondBuyPrice> 0.0</secondBuyPrice>
<secondBuyQuantity> 0</secondBuyQuantity>
<secondSellPrice> 0.0</secondSellPrice>
<secondSellQuantity> 0</secondSellQuantity>
<thirdBuyPrice> 0.0</thirdBuyPrice>
<thirdBuyQuantity> 0</thirdBuyQuantity>
<thirdSellPrice> 0.0</thirdSellPrice>
<thirdSellQuantity> 0</thirdSellQuantity>
<calendar>
<time> 1319038099446</time>
<timezone> America/New_York</timezone>
</calendar>
</org.yccheok.jstock.engine.Stock>
</java.util.Collections>
I am trying to extract the tag values of the code inner tag and changePricePercentage in C#. I am also trying to pre-populate a DataTable with these values. How do I handle the inner tag of code as well? Even though I am no expert, here is my C# source code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Data;
namespace XMLParser
{
class Program
{
static void Main(string[] args)
{
DataTable table = new DataTable();
table.Columns.Add("code", typeof(string)); ;
table.Columns.Add("changePricePercentage", typeof(double));
// Create a new XmlDocument
XmlDocument doc = new XmlDocument();
// Load data
doc.Load(#"C:\...\realtimestock.xml");
// Set up namespace manager for XPath
// Get forecast with XPath
//XmlNodeList nodes = doc.SelectNodes("org.yccheok.jstock.engine.Stock", ns);
XmlNodeList nodes = doc.SelectNodes("org.yccheok.jstock.engine.Stock");
// You can also get elements based on their tag name and namespace,
// though this isn't recommended
//XmlNodeList nodes = doc.GetElementsByTagName("org.yccheok.jstock.engine.Stock");
// "http://xml.weather.yahoo.com/ns/rss/1.0");
foreach (XmlNode node in nodes)
{
// Console.WriteLine("{0}: {1}, {2}F - {3}F",
// node.Attributes["code"].InnerText,
// node.Attributes["changePricePercentage"].InnerText);
Console.WriteLine("1: {0} 2: {1}", node.Attributes["code"].InnerText,
node.Attributes["changePricePercentage"].InnerText);
table.Rows.Add(node.Attributes["code"].InnerText, node.Attributes["changePricePercentage"].InnerText);
Console.ReadKey();
}
}
}
}
How would I get my code to accomplish this task?
P.S. This Stackoverflow editor would not accept my XML code properly so I had to edit with the actual symbol names. Sorry
Thanks
Try this:
XmlNodeList nodes = doc.SelectNodes("//org.yccheok.jstock.engine.Stock");
foreach (XmlElement element in nodes)
{
Console.WriteLine("1: {0} 2: {1}",
element.SelectSingleNode("code").InnerText,
element.SelectSingleNode("changePricePercentage").InnerText);
}
Console.ReadKey();
Your code and changePricePercentage nodes are elements, not attributes, that was your mistake.