I need to write a c# code to extract attribute info from an XML when the validation fails. The code I have below is able to give me the exact attribute that fails the validation but I need additional info from attributes present in the parent nodes as well.
XML:
<Payload xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlVersion="1.0" createDate="2023-11-07T14:23:08" messageType="TEST">
<Orders>
<OrderHeader resultsIndicator="F" orderNumber="2000100" orderStatus="FIN" latestShipDate="4/23/2023 12:00:00 AM" cusNumber="791053" cusName="Apple, Ms.Rose" deliveryTerms="HOME" paymentType="AMEX" Destination="TX">
<OrderDetail resultsIndicator="F" lot="1234" sequence="01" invoice="FGD123401" finalDestination="75013" resultsMessage="DELIVERED" brandNumber="100141" brandName="LG">
<OrderCostingDetail expenseCode="ADMIN" expenseCategory="ADM" rate="2499.50" indicator="F" qualifier="SALE" unitCost="2499.50" level="002"/>
<OrderCostingDetail expenseCode="ADMIN" expenseCategory="ADM" rate="125.00" indicator="F" qualifier="SALE" unitCost="" level="002"/>
<OrderCostingDetail expenseCode="ADMIN" expenseCategory="ADM" rate="5879.20" indicator="F" qualifier="SALE" unitCost="5879.20" level="002"/>
</OrderDetail>
</OrderHeader>
<OrderHeader resultsIndicator="I" orderNumber="2000101" orderStatus="INIT" latestShipDate="12/10/2023 12:00:00 AM" cusNumber="56782" cusName="Roy, Mr.Ralph" deliveryTerms="HOME" paymentType="VISA" Destination="TX">
<OrderDetail resultsIndicator="I" lot="1234" sequence="01" invoice="FGD123401" finalDestination="75013" resultsMessage="DELIVERED" brandNumber="100141" brandName="LG">
<OrderCostingDetail expenseCode="ADMIN" expenseCategory="ADM" rate="24.00" indicator="I" qualifier="SALE" unitCost="24.00" level="004"/>
</OrderDetail>
</OrderHeader>
</Orders>
</Payload>
Code:
private static void PerformValidation(XmlTextReader xmlTextReader, XmlSchemaSet schemas)
{
if (schemas == null)
{
throw new ArgumentNullException("schemas");
}
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas = schemas;
settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings; //sarul1
// settings.ValidationEventHandler += (sender, args) => error = ValidationCallback(sender, args);
string chkatt = string.Empty;
using (XmlReader reader = XmlReader.Create(xmlTextReader, settings))
{
try
{
do
{
chkatt = string.Concat("orderNo.: ",reader.GetAttribute("orderNumber"), ", Lot:", reader.GetAttribute("lot"), ", Seq:", reader.GetAttribute("sequence"));
} while (reader.Read());
}
catch(Exception ex)
{
string error = ex.Message.ToString() + chkatt;
}
finally
{
reader.Close();
}
}
}
I call the above method in my main function to validate if there are any NULL fields, against a predefined schema. I get an error
The 'unitCost' attribute is invalid...The string '' is not a valid Decimal value
I need to add other attribute info like orderNumber, Lot and Sequence to this message (in this case: orderNumber = 2000100, Lot = 1234, Seq = 01) which I am not able to do with this code.
Please help me move forward!
The PerformValidation
function lacked context in the error messages because it didn't keep track of attribute values in parent nodes.
consider this updated code:
private static void PerformValidation(XmlTextReader xmlTextReader, XmlSchemaSet schemas)
{ if (schemas == null) { throw new ArgumentNullException("schemas"); }
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas = schemas;
settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings;
string orderNumber = string.Empty;
string lot = string.Empty;
string sequence = string.Empty;
using (XmlReader reader = XmlReader.Create(xmlTextReader, settings))
{
try
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name == "OrderHeader")
{
orderNumber = reader.GetAttribute("orderNumber");
}
else if (reader.Name == "OrderDetail")
{
lot = reader.GetAttribute("lot");
sequence = reader.GetAttribute("sequence");
}
}
else if (reader.NodeType == XmlNodeType.Attribute && reader.Value == string.Empty)
{
string errorMessage = $"Validation error in OrderNo.: {orderNumber}, Lot: {lot}, Seq: {sequence}. ";
// Handle or log the error message as needed
Console.WriteLine(errorMessage);
}
}
}
catch (Exception ex)
{
string error = ex.Message.ToString();
// Handle or log the exception as needed
Console.WriteLine(error);
}
finally
{
reader.Close();
}
}
}
This code introduced variables (orderNumber, lot, and sequence) to store these values, allowing for more informative error messages when validation errors occurred.
give it a try and let me know if further modifications are needed. and kindly don't forget to mark as an answer if this answer has solved your question. :)