I am getting data with the help of api
for credit card information. The data I got is as follows.
<<?xml version="1.0" encoding="ISO-8859-9"?>
<CC5Response>
<ProcReturnCode>00</ProcReturnCode>
<Response>Approved</Response>
<Extra>
<PAN1LABEL>PRICE</PAN1LABEL>
<PAN2INDEXORDER>1</PAN2INDEXORDER>
<PAN2STATUS>NO</PAN2STATUS>
<SAFEKEYLASTMODIFIED>11/22/333</SAFEKEYLASTMODIFIED>
<PAN2INDEXACCOUNTCLOSURE>00</PAN2INDEXACCOUNTCLOSURE>
<PAN1STATUS>NO</PAN1STATUS>
<PAN1INDEXACCOUNTCLOSURE>00</PAN1INDEXACCOUNTCLOSURE>
<PAN2EXPIRY>00.1111</PAN2EXPIRY>
<PAN1OWNER>JOHN DAVIS</PAN1OWNER>
<PAN2LABEL>PRODUCT BUY</PAN2LABEL>
<PAN2DESCRIPTION>DESCRIPION</PAN2DESCRIPTION>
<PAN1>1111 22** **** 3333</PAN1>
<PAN2>1111 22** **** 3333</PAN2>
<PAN2OWNER>JOHN DAVIS</PAN2OWNER>
<PAN1EXPIRY>02.2025</PAN1EXPIRY>
<NUMBEROFPANS>3</NUMBEROFPANS>
<PAN1INDEXORDER>1</PAN1INDEXORDER>
<PAN1DESCRIPTION>PRODUCT NO</PAN1DESCRIPTION>
</Extra>
</CC5Response>
I need to get the data with the whole word "PAN" in it. I'll add this to the user's saved card info screen. I tried a few times but it didn't work. Here are the codes i tried
List<string> list = new List<string>();
list.add(responseFromServer); //"responseFromServer" data from api
string[] getPanArray = list.ToArray();
List<string> panlist = new List<string>();
string pan = "PAN";
foreach (var item in getPanArray)
{
if (item.Contains(pan))
{
panlist.Add(item);
}
}
Latter
List<string> list = new List<string>();
list.Add(responseFromServer);
String[] test = list.ToArray();
String text = "PAN";
String[] result = test.Where(s =>
{
Boolean isInThere = true;
Char[] textArray = text.ToCharArray();
foreach (Char c in textArray)
{
if (!s.Contains(c))
isInThere = false;
}
return isInThere;
}).ToArray();
CodePudding user response:
So, since responseFromServer
is a string
, first, parse the string into an XDocument
.
using System.Xml.Linq;
...
var response = XDocument.Parse(responseFromServer);
Then you can use LINQ to filter out the elements you are interested in.
using System.Linq;
...
var justPans = response
.Element("CC5Response")
.Element("Extra")
.Elements().Where(e => e.Name.LocalName.Contains("PAN"));
Gives you an IEnumerable
of XElement
for just the PAN
elements. Then you can extract the contexts of valid text elements.
var panContents = justPans
.Select(e => e.FirstNode)
.OfType<XText>()
.Select(t => t.Value)
.ToList();
This is demoed here.
CodePudding user response:
That is a horribly formatted XML, and its contents do not make any sense. For example, it says it has 3 PANs:
<NUMBEROFPANS>3</NUMBEROFPANS>
But I only see two.
Furthermore, what is the purpose of having variable starting index and then have it the same for two entries?
<PAN1INDEXORDER>1</PAN1INDEXORDER>
In short, this is next to impossible to parse easily using direct deserialization into classes which is how you are supposed to parse XML in C#.
The data from the API should be reformatted by the host to look like this before they send it to you:
<Extra>
<Items>
<Item>
<INDEXORDER>1</INDEXORDER>
<LABEL>PRICE</LABEL>
<STATUS>NO</STATUS>
<INDEXACCOUNTCLOSURE>00</INDEXACCOUNTCLOSURE>
<OWNER>JOHN DAVIS</OWNER>
<PAN>1111 22** **** 3333</PAN>
<EXPIRY>02.2025</EXPIRY>
<DESCRIPTION>PRODUCT NO</DESCRIPTION>
</Item>
<Item>
<INDEXORDER>1</INDEXORDER>
<LABEL>PRODUCT BUY</LABEL>
<STATUS>NO</STATUS>
<INDEXACCOUNTCLOSURE>00</INDEXACCOUNTCLOSURE>
<OWNER>JOHN DAVIS</OWNER>
<PAN>1111 22** **** 3333</PAN>
<EXPIRY>00.1111</EXPIRY>
<DESCRIPTION>DESCRIPION</DESCRIPTION>
</Item>
</Items>
<SAFEKEYLASTMODIFIED>11/22/333</SAFEKEYLASTMODIFIED>
</Extra>
In order for it to be easily parsed. Then it is a simple matter of making model classes:
public class Item
{
public int IndexOrder;
public string Label;
public string Status;
public int IndexAccountClosure;
public string Owner;
public string PAN;
public string Expiry;
public string Description;
}
public class ExtraData
{
public Item[] Items;
public string SafeKeyLastModified;
}
public class CCSResponse
{
public int ProcReturnCode;
public string Response;
public ExtraData Extra;
}
And then letting XMLSerializer
do its job:
string XMLTextFromAPI = YourAPICallHere();
CCSResponse data;
XmlSerializer serializer = new XmlSerializer(typeof(CCSResponse));
using (TextReader reader = new StringReader(XMLTextFromAPI)) {
data = (CCSResponse)serializer.Deserialize(reader);
}
Afterwards you can just access the data like this:
foreach (Item i in data.Extra.Items) {
// do whatever you need with those PANs
}
Anything other than that, and you are asking for trouble both in writing and in maintaining that code later.
TL;DR — sometimes a proper solution is not to accept to work with garbage data that you are given and ask them to change it, at least that's what I would do if I were in your place.
I am sure someone else will post an actual answer on how to parse that garbage data which will probably involve regex or LINQ in some way.