I would like to parse an XML file using c#. I am a beginner in that field so I need your help please.
Before I ask my question I checked on the net, and found that there is 2 ways to parse XML, either we should use something called XmlDocument or XmlReader so I want to know what is best to use in my case.
Here is exactly what I want to do : I have an XML, I would like to loop through all nodes and search for a specific string inside the node and subnodes and if I found MYSTRING, I note the name of the node with True, and if not, I note the name of the node with False.
I will show you a part of the XML which is too long to make it more clear.
If you look near the end of the XML there is MYSTRING.
What I want is to loop over all the Jobs in the XML, and check if the job has or not the MYSTRING...Some jobs have it and some others no.
My questions are : what do use ? XML Reader or Document ?
and how to check if inside a node (Job in this example) and the nodes inside it , there is a string called MyString or not.
Thanks in advance to anyone who can Help me.
<?xml version="1.0" encoding="UTF-8"?>
<DSExport>
<Header CharacterSet="CP1252" ExportingTool="IBM InfoSphere DataStage Export" ToolVersion="8" ServerName="PAR.SL.PRES" ToolInstanceID="dstage1" Date="2017-10-12" Time="15.02.49" ServerVersion="11.5"/>
<Job Identifier="JxD" TimeModified="11.59.45">
<Record Identifier="ROOT" Type="JobDF" Readonly="0">
<Property Name="Name">Suivi</Property>
<Property Name="Description">Initialisation des datasets</Property>
<Property Name="NextID">29</Property>
<Property Name="ControlAfterSubr">0</Property>
<Collection Name="Parameters" Type="Parameters">
<SubRecord>
<Property Name="Name">pathdataset</Property>
<Property Name="Prompt">pathdataset</Property>
<Property Name="Default">/home/intdwh/DSdataset</Property>
<Property Name="ParamType">5</Property>
<Property Name="ParamLength">0</Property>
<Property Name="ParamScale">0</Property>
</SubRecord>
</Collection>
<Property Name="Container">V0</Property>
<Property Name="FullDescription" PreFormatted="1">Ce job :
- créé des datasets vides
- vides les datasets des données
Les datasets auquels sont rajoutés 1 informations : VERSION
Modification du 05/02/2013 par A.dupont
la variable "LaDate" retourne MYSTRING\(20)</Property>
</Record>
</Job>
</DSExport>
Unfortunatly No one gave me an exact answer of what I wanted here, but I finally got the solution my self;
I used XmlDocument
I used the option SelectNodes to get my nodes, but the most important was to use sometimes the .//MyNode to get relative nodes, based on current one..If we don't use .// we will get all nodes in the documents not the ones relatives to current nodes.
I used something like that to succeed
XmlNodeList PropertyNodes = itemNode.SelectNodes(".//Property");
Thanks anyway to anyone who tried to help.
Related
I have this template from a bank that is used to make payments on bank account transfers.
See xml below. I have included the sample data that has to be entered when sending the file to the bank.
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>Cart Urgent28052018_57894</MsgId>
<CreDtTm>2018-06-29T11:52:23</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>667896.00</CtrlSum>
<InitgPty>
<Nm>CART LIMITED</Nm>
<Id>
<OrgId>
<Othr>
<Id>S001234/PJones</Id>
<SchmeNm>
<Cd>CUST</Cd>
</SchmeNm>
</Othr>
</OrgId>
</Id>
</InitgPty>
</GrpHdr>
<PmtInf>
<PmtInfId>Payment for addon development SAP B1</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>false</BtchBookg>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>667896.00</CtrlSum>
<PmtTpInf>
<InstrPrty>HIGH</InstrPrty>
</PmtTpInf>
<ReqdExctnDt>2018-06-29</ReqdExctnDt>
<Dbtr>
<Nm>CART LIMITED</Nm>
</Dbtr>
<DbtrAcct>
<Id>
<Othr>
<Id>0112345110846</Id>
</Othr>
</Id>
<Ccy>KES</Ccy>
</DbtrAcct>
<DbtrAgt>
<FinInstnId>
<BIC>SBICKENX</BIC>
</FinInstnId>
</DbtrAgt>
<CdtTrfTxInf>
<PmtId>
<EndToEndId>156335578965</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="KES">667896.00</InstdAmt>
</Amt>
<ChrgBr>DEBT</ChrgBr>
<CdtrAgt>
<FinInstnId>
<BIC>DTKEKENA</BIC>
<ClrSysMmbId>
<MmbId>63000</MmbId>
</ClrSysMmbId>
</FinInstnId>
</CdtrAgt>
<Cdtr>
<Nm>EOH SEAL LTD</Nm>
<PstlAdr>
<StrtNm>P.O. Box 10496</StrtNm>
<TwnNm>Nairobi</TwnNm>
<Ctry>KE</Ctry>
<AdrLine>P.O. Box 10496</AdrLine>
<AdrLine>00100 NAIROBI</AdrLine>
</PstlAdr>
</Cdtr>
<CdtrAcct>
<Id>
<Othr>
<Id>0112406001</Id>
</Othr>
</Id>
</CdtrAcct>
<RmtInf>
<Ustrd>Cart Urgent28052018_57894</Ustrd>
</RmtInf>
</CdtTrfTxInf>
</PmtInf>
</CstmrCdtTrfInitn>
</Document>
The file is quite long as has to be in the format given. The black letters represent the details to be passed to the xml. To test if I understood what data goes where I filled it manually and sent to bank for testing. That is all good now.
I have a SAP addon program that captures details from a form and generates a list. Each payment must follow this structure.
Looking at the below:
<Nm>CART LIMITED</Nm>
<Id>
<OrgId>
<Othr>
<Id>S001234/PJones</Id>
<SchmeNm>
<Cd>CUST</Cd>
</SchmeNm>
</Othr>
</OrgId>
</Id>
Is creating a class with all properties according to the template the best way to create the xml needed.
How do I stagger the
<Id>
<OrgId>
<Othr>
as in the case above?
Also the <CtrlSum>667896.00</CtrlSum> is found in the group header and payment info tags. How do I deal with this?
For what i see, the problem is you have a addon in SAP to specify multiple payments methods, but in the XML template given from the bank you don't the structure for multiple payments, so you need to get this information to know how can you work with it.
when you have this information you can use a better XML template with VS or another tool to generate the correct class to work with the XML
I'm looking for a fast and efficient way to retreive 2 strings from multiple xml files.
The files them selves aren't that big only 50kb to 100kb and the number of files can range from none to 100. I've included a sample of a very small xml file i'll be using. All xml files will be the same format and there's only 2 things i need to know from all files namely:
<Company>test bv.</Company>
<Ship>sss testing</Ship>
i want to store these strings in a struct/class since i cannot use Tuple in .net 3.5 (or am i mistaking?)
so the question: what is the most efficient way to do this? using Xdocument? using xmlReader? or something else?
<?xml version="1.0" encoding="utf-8"?>
<Collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Customer>
<ID>-1</ID>
<Updated>true</Updated>
<Company>test bv.</Company>
<Ship>sss testing</Ship>
<Adress>fggfgggff gvg</Adress>
<City>fgcgg</City>
<ZipCode>5454fc</ZipCode>
<Country>fcgggff</Country>
<BTW_Nmbr>55</BTW_Nmbr>
<IsTempCustomer>true</IsTempCustomer>
<PhoneNumbers>
<ContactData>
<ID>21</ID>
<Updated>true</Updated>
<Description>455656567</Description>
<Name>ghbbvh</Name>
<IsSendable>false</IsSendable>
</ContactData>
<ContactData>
<ID>22</ID>
<Updated>true</Updated>
<Description>2315098234146124302134</Description>
<Name>asdfawegaebf</Name>
<IsSendable>false</IsSendable>
</ContactData>
</PhoneNumbers>
<EmailAdresses />
</Customer>
<Order>
<ID>-1</ID>
<Updated>true</Updated>
<OrderNr>10330200</OrderNr>
<OrderDate>1-1-2005</OrderDate>
<StartDate>10-9-2013</StartDate>
<ExpirationDate>20-10-2013</ExpirationDate>
<Executor>Andre de Zwart</Executor>
<Executors />
<Reference />
<OrderDetail />
<IsDigital>true</IsDigital>
</Order>
<Materials>
<MaterialData>
<ID>108</ID>
<Updated>true</Updated>
<Description>ffdffggfg</Description>
<Amount>34</Amount>
</MaterialData>
<MaterialData>
<ID>109</ID>
<Updated>true</Updated>
<Description>ffccff</Description>
<Amount>45</Amount>
</MaterialData>
</Materials>
<HourExpenses>
<HourExpensesData>
<ID>43850</ID>
<Updated>true</Updated>
<Date>2013-10-06T00:00:00</Date>
<Notes>lala</Notes>
<Day>Sunday</Day>
<Hours>0.01</Hours>
<BusinessHours>0.01</BusinessHours>
<TravledHoursTo>0</TravledHoursTo>
<TravledHoursFrom>0</TravledHoursFrom>
<Start>2013-10-06T12:27:00</Start>
<Stop>2013-10-06T12:27:00</Stop>
</HourExpensesData>
<HourExpensesData>
<ID>43849</ID>
<Updated>true</Updated>
<Date>2013-09-17T00:00:00</Date>
<Notes>oke dus ik ben nu lekker aan het werk en ik typ wat spul er bij</Notes>
<Day>Tuesday</Day>
<Hours>0</Hours>
<BusinessHours>0.01</BusinessHours>
<TravledHoursTo>0</TravledHoursTo>
<TravledHoursFrom>0</TravledHoursFrom>
<Start>2013-09-17T12:31:31</Start>
<Stop>2013-09-17T12:31:32</Stop>
</HourExpensesData>
<HourExpensesData>
<ID>43855</ID>
<Updated>true</Updated>
<Date>2013-10-03T00:00:00</Date>
<Notes>test</Notes>
<Day>Thursday</Day>
<Hours>0</Hours>
<BusinessHours>0</BusinessHours>
<TravledHoursTo>12</TravledHoursTo>
<TravledHoursFrom>12</TravledHoursFrom>
<Start>0001-01-01T00:00:00</Start>
<Stop>0001-01-01T00:00:00</Stop>
</HourExpensesData>
</HourExpenses>
<TravelExpenses>
<TravelExpensesData>
<ID>672</ID>
<Updated>true</Updated>
<Date>2013-09-27T00:00:00</Date>
<Notes />
<KmTo>45</KmTo>
<KmFrom>45</KmFrom>
<Declaration>0</Declaration>
</TravelExpensesData>
</TravelExpenses>
<Signatures>
<ID>-1</ID>
<Updated>true</Updated>
<OrderID>10330200</OrderID>
<Completed>false</Completed>
<Notes>yay het werkt ;D</Notes>
</Signatures>
<RemovedDataList />
</Collection>
I would just use LINQ to XML in the simplest possible way:
var query = from file in files
let doc = XDocument.Load(file)
from customer in doc.Descendants("Customer")
select new {
Company = (string) customer.Element("Company"),
Ship = (string) customer.Element("Ship")
};
I'd expect that to be pretty quick already - but you should work out what your exact performance requirements are, then test them. (You almost certainly don't need "the most efficient" way - you need a sufficiently efficient way, whilst keeping the code readable.)
Note that if you want the values to be propagated out of the current method, you should create your own class to represent the company/ship pair.
Thank you all for suggesting things and helping whenever in need.
Yesterday I was trying to develop and web app in asp.net 4.0 where I needed to parse the data from xml and save it in database. But before that I will also have to validate it.
I tried using .net provided tool xsd.exe to generate the schema file, but I dont know how will it know to mark which nodes or attributes are compulsory?
Like in my xml below items are mandatory
Root node <Market>
<Login> and its sub element
<ProductType> and its <ProductTypeID/>
The attribute DML is mandatory but should have only 3 values NONE, PUT or MODIFY
<ProductType> may or may not have <ProductItem>
If <ProductItem> is present then it should have <ProductItemID>
<ProductItem> may or may not have <Brand>
If <Brand> is present then it should have <BrandID>
Below is my xml
<?xml version="1.0" encoding="utf-8" ?>
<Market>
<Login>
<LoginId />
<Password />
</Login>
<ProductType DML="NONE">
<ProductTypeID/>
<Name/>
<Detail/>
<ProductItem DML="PUT">
<ProductItemID/>
<Name/>
<Detail/>
<Brand DML="PUT">
<BrandID/>
<Name/>
<Detail/>
</Brand>
<Brand DML="MODIFY">
<BrandID/>
<Name/>
<Detail/>
</Brand>
</ProductItem>
<ProductItem DML="MODIFY">
<ProductItemID/>
<Name/>
<Detail/>
</ProductItem>
</ProductType>
</Market>
How and where should I specify all the mandatory and optional parameters, so that my xsd is generated as per the requirement.
Thanks,
M.
xsd.exe can only try to infer, which elements/attributes are in you xml, but it cannot find out which information is mandatory. But this is a good startingpoint.
use a graphical XML_Schema_Editor to edit the genrated xsd to mark your mandatory fields. That is much easier than learning the xsd-language
I don't think XSD support nested XML. I would try to load the XML into an XmlDocument and check mandatory fields manually.
I'm trying to do very simple operations on a .cxml file. As you know it's basically an .xml file. This is a sample file I created to test the application:
<?xml version="1.0" encoding="utf-8"?>
<Collection xmlns:p="http://schemas.microsoft.com/livelabs/pivot/collection/2009" SchemaVersion="1.0" Name="Actresses" xmlns="http://schemas.microsoft.com/collection/metadata/2009">
<FacetCategories>
<FacetCategory Name="Nationality" Type="LongString" p:IsFilterVisible="true" p:IsWordWheelVisible="true" p:IsMetaDataVisible="true" />
</FacetCategories>
<!-- Other entries-->
<Items ImgBase="Actresses_files\go144bwo.0ao.xml" HrefBase="http://www.imdb.com/name/">
<Item Id="2" Img="#2" Name="Anna Karina" Href="nm0439344/">
<Description> She is a nice girl</Description>
<Facets>
<Facet Name="Nationality">
<LongString Value="Danish" />
</Facet>
</Facets>
</Item>
</Items>
<!-- Other entries-->
</Collection>
I can't get any functioning simple code like:
XDocument document = XDocument.Parse(e.Result);
foreach (XElement x in document.Descendants("Item"))
{
...
}
The test on a generic xml is working. The cxml file is correctly loaded in document.
While watching the expression:
document.Descendants("Item"), results
the answer is:
Empty "Enumeration yielded no results" string
Any hint on what can be the error? I've also add a quick look to get Descendants of Facet, Facets, etc., but there are no results in the enumeration. This obviously doesn't happen with a generic xml file I used for testing. It's a problem I have with .cxml.
Basically your XML defines a default namespace with the xmlns="http://schemas.microsoft.com/collection/metadata/2009" attribute:
That means you need to fully qualify your Descendants query e.g.:
XDocument document = XDocument.Parse(e.Result);
foreach (XElement x in document.Descendants("{http://schemas.microsoft.com/collection/metadata/2009}Item"))
{
...
}
If you remove the default namespace from the XML your code actually works as-is, but that is not the aim of the exercise.
See Metadata.CXML project under http://github.com/Zoomicon/Metadata.CXML sourcecode for LINQ-based parsing of CXML files.
Also see ClipFlair.Metadata project at http://github.com/Zoomicon/ClipFlair.Metadata for parsing one's CXML custom facets too
BTW, at http://ClipFlair.codeplex.com can checkout the ClipFlair.Gallery project for how to author ASP.net web-based forms to edit metadata fragments (parts of CXML files) and merge them together in a single one (that you then convert periodically to DeepZoom CXML with PAuthor tool from http://pauthor.codeplex.com).
If anyone is interested in doing nesting (hierarchy) of CXML collections see
http://github.com/Zoomicon/Trafilm.Metadata
and
http://github.com/Zoomicon/Trafilm.Gallery
I am trying to get the data from input xml message using functoids. But this doesn't seem to work. Below is my XML snippet
<?xml version="1.0" ?>
<ROOT>
<COMPANIES>
<COMPANY>
<NAME>FOO CORP</name>
</COMPANY>
<COMPANY>
<NAME>ACME CORP</name>
</COMPANY>
</COMPANIES>
<INFORMATIONS>
<INFORMATION>
<TESTING>
<TESTS>
<NAME>1221</NAME>
<TEST>
<TEXT>I AM SAM</TEXT>
</TEST>
</TESTS>
<TESTS>
<NAME>21</NAME>
<TEST>
<TEXT>FADFDF</TEXT>
</TEST>
</TESTS>
<TESTS>
<NAME>3001</NAME>
<TEST>
<TEXT>SGFGSDFG</TEXT>
</TEST>
</TESTS>
<TESTS>
<NAME>4569</NAME>
<TEST>
<TEXT>12312</TEXT>
</TEST>
</TESTS>
</TESTING>
<INFORMATION>
</INFORMATIONS>
</ROOT>
First I am trying to loop through COMPANY and get the NAME "ACME CORP". but which ever functoid i use (scripting, string extract etc) I always get the FOO CORP. I even tried inline XSLT but that also doesn't seem to work. Any idea how to get the 2nd COMPANY name?
Secondly, I have mapped <TEXT> directly to <node> in my destination schema. What i get is only 2 values from <TEXT>. Not all the <TEXT> are mapped to my <node>. Output i am getting is
I don't get is
I AM SAM
FADFDF
I don't get
<node>SGFGSDFG</node>
<node>12312</node>
Any one knows how i could get the values?
Thanks in advance
cheers,
Karthik
Q1: How to get the NAME of the second COMPANY?
1) Add Iteration functoid (Advanced Functoids) and connect to COMPANY node in your source schema
2) Add Equal functiod (Logical Functoids) and connect to Iteration functoid
3) Configure Equal functoid; add constant value 2
4) Add Value Mapping (Flattening) functoid (Advanced Functoids)
5) Connect output of Equal to input of Value Mapping
6) Connect NAME emlement of source schema to input of Value Mapping
7) Connect output of Value Mapping to destination schema element
Q2: Not all source TEXT elements are transformed to destination node
This seems to be a side effect of your mapping concering Q1 and I cannot reproduce your error.
Check minOccurs and maxOccurs of your source and destination schema for the elements/nodes in question.