NullReferenceException unhandled by user code while changing XML document - c#

I am getting the error : NullReferenceException was unhandled by user code , object reference not set to an instance of an object. While I want to change the element of an xml file. this is the code the error is generated on :
doc2.SelectSingleNode("/Document/CstmrCdtTrfInitn/GrpHdr/MsgId", nsmgr).InnerText = bank.Afkorting + "-0001";
This is the previous code :
XmlDocument doc2 = new XmlDocument();
doc2.Load(#"C:\Users\Kevin\Desktop\xsd\betalingen_sepa.xml");
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc2.NameTable);
nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
DagboekFinancieel bank = os.FindObject<DagboekFinancieel>(CriteriaOperator.Parse("[Omschrijving] = ?", opdracht.Bank));
doc2.SelectSingleNode("/Document/CstmrCdtTrfInitn/GrpHdr/MsgId", nsmgr).InnerText = bank.Afkorting + "-0001";
string naamFile = bank.Afkorting + "-0001";
doc2.Save(#"C:\" + naamFile + ".xml");
This is the original XML file I got :
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>#ref_xml#</MsgId>
<CreDtTm>#datum_tijd_xml#</CreDtTm>
<NbOfTxs>#aantal_transacties#</NbOfTxs>
<InitgPty>
<Nm>#afzender_naam#</Nm>
<Id>
<OrgId>
<Othr>
<Id>#afzender_btw_nr#</Id>
<Issr>KBO-BCE</Issr>
</Othr>
</OrgId>
</Id>
</InitgPty>
</GrpHdr>
<PmtInf>
<PmtInfId>#ref_payment_block#</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>true</BtchBookg>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt>#datum_uitvoering#</ReqdExctnDt>
<Dbtr>
<Nm>#afzender_naam#</Nm>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>#afzender_iban#</IBAN>
</Id>
</DbtrAcct>
<DbtrAgt>
<FinInstnId>
<BIC>#afzender_bic#</BIC>
</FinInstnId>
</DbtrAgt>
<ChrgBr>#kosten#</ChrgBr>
<CdtTrfTxInf>
<PmtId>
<EndToEndId>#ref_end_to_end#</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="#munt#">#bedrag#</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC>#leveran_bic#</BIC>
</FinInstnId>
</CdtrAgt>
<Cdtr>
<Nm>#leveran_naam#</Nm>
<PstlAdr>
<Ctry>#leveran_land#</Ctry>
<AdrLine>#leveran_straat#</AdrLine>
<AdrLine>#leveran_wpl#</AdrLine>
</PstlAdr>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>#leveran_iban#</IBAN>
</Id>
</CdtrAcct>
<RmtInf>
<Ustrd>#leveran_ref#</Ustrd>
<Strd>
<CdtrRefInf>
<Tp>
<CdOrPrtry>
<Cd>#gestruct_mededeling_soort1#</Cd>
</CdOrPrtry>
<Issr>#gestruct_mededeling_soort2#</Issr>
</Tp>
<Ref>#gestruct_mededeling#</Ref>
</CdtrRefInf>
</Strd>
</RmtInf>
</CdtTrfTxInf>
</PmtInf>
</CstmrCdtTrfInitn>
</Document>

Your xml namespace is not correct. Use it like
nsmgr.AddNamespace("ns", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03");
doc2.SelectSingleNode("/ns:Document/ns:CstmrCdtTrfInitn/ns:GrpHdr/ns:MsgId", nsmgr).InnerText = "some text";

Related

insert element after selected node

Am trying to add a new element called entity after the last entity but it keeps adding it inside the selected entity. To understand better this is my xml sample.
<Root>
<Class Name="ECMInstruction" Style="Top">
<Entity Id="1" Name="DocumentInformation" />
<Entity Id="2" Name="CustomerInformation" />
<Property Id="1" Name="DocumentTitle">
</Property>
<Property Id="2" Name="DateCreated">
<Lists>
<ListName>ws_Users</ListName>
<ListName>dfdfdfd</ListName>
</Lists>
</Property>
<Property Id="3" Name="Deadline">
</Property>
</Class>
</Root>
This is how it looks like after is inserted. I've tried using insertAfter but it gives me error.
<Entity Id="1" Name="DocumentInformation">
<Entity Id="2" Name="sds" />
</Entity>
The code:
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load("sample.xml");
XmlNodeList cnode = xmldoc.DocumentElement.SelectNodes("//Class[#Name='" + CurrentClass + "']/Entity");
foreach (XmlNode c in cnode)
{
int value = 0;
String entitycount = cnode.Count.ToString();
int.TryParse(entitycount, out value);
value = value + 1;
XmlElement root = xmldoc.CreateElement("Entity");
root.SetAttribute("Id", value.ToString());
root.SetAttribute("Name", EntityNametxt.Text);
c.AppendChild(root);
xmldoc.Save("sample.xml");
}
"I've tried using insertAfter but it gives me error. "
As per documentation, InsertAfter() should be called on parent node of referenced XmlNode (the 2nd argument of the method), otherwise ArgumentException will be thrown :
//instead of this : c.AppendChild(root);
//..you could do as follow :
c.ParentNode.InsertAfter(root, c);

delete child node with specific value

Am trying to delete a list name containing the value "dfdfdfd" from an XPath
XmlNode names = LoadDocument(xml).DocumentElement.SelectSingleNode("//Class[#Name='" + getCurClass() + "']/Property[#Id='" + i + "']/Lists[contains(ListName,'ws_Users')]");
after I execute this statement:
names.RemoveChild(names.FirstChild);
but I nothing happens.
My XML :
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Class Name="ECMInstruction" Style="Top">
<Entity Id="1" Name="DocumentInformation" />
<Property Id="1">
</Property>
<Property Id="2">
<Lists>
<ListName>ws_Users</ListName>
<ListName>dfdfdfd</ListName>
</Lists>
</Property>
</Class>
</Root>
Thanks for the help
You need to save the modified XmlDocument object back to file :
XmlDocument doc = LoadDocument(xml);
XmlNode names = doc.DocumentElement.SelectSingleNode("//Class[#Name='" + getCurClass() + "']/Property[#Id='" + i + "']/Lists[contains(ListName,'ws_Users')]");
names.RemoveChild(names.FirstChild);
//save `doc` back to file :
doc.Save("path_to_the_xml_file.xml");
or this way :
XmlNode names = LoadDocument(xml).DocumentElement.SelectSingleNode("//Class[#Name='" + getCurClass() + "']/Property[#Id='" + i + "']/Lists[contains(ListName,'ws_Users')]");
names.RemoveChild(names.FirstChild);
//save owner `XmlDocument` back to file :
names.OwnerDocument.Save("path_to_the_xml_file.xml");

XDocument losing line number

I'm using XDocument to parse my XML File, but when I try to read the line number of a XNode or a XElement, it's always equal to zero.
I tried different ways to parse it:
foreach (XElement node in xDoc.Root.Descendants("nodeName"))
or
xDoc.XPathSelectElement("nodeName")
and each time ((IXmlLineInfo)node).LineNumber returns 0!
I'm using a XmlNamespaceManager.
Did I miss something?
Thanks in advance!
Edit :
Here is the concerned Xml as asked.
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<CstmrDrctDbtInitn>
<GrpHdr>
<MsgId>XXXXXXXXX</MsgId>
<CreDtTm>2013-06-12T00:00:00</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>136.82</CtrlSum>
<InitgPty>
<Nm>name</Nm>
<Id>
<OrgId>
<Othr>
<Id>XXXXXXXXX</Id>
</Othr>
</OrgId>
</Id>
</InitgPty>
</GrpHdr>
<PmtInf>
<PmtInfId>275-20130612-FIRST</PmtInfId>
<PmtMtd>DD</PmtMtd>
<BtchBookg>true</BtchBookg>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>136.82</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<LclInstrm>
<Cd>CORE</Cd>
</LclInstrm>
<SeqTp>RCUR</SeqTp>
</PmtTpInf>
<ReqdColltnDt>2013-06-05</ReqdColltnDt>
<Cdtr>
<Nm>name</Nm>
<PstlAdr>
<Ctry>BE</Ctry>
<AdrLine>XXXXXXXXX</AdrLine>
<AdrLine>XXXXXXXXX</AdrLine>
</PstlAdr>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>XXXXXXXXX</IBAN>
</Id>
</CdtrAcct>
<CdtrAgt>
<FinInstnId>
<BIC>XXXXXXXXX</BIC>
</FinInstnId>
</CdtrAgt>
<ChrgBr>SLEV</ChrgBr>
<CdtrSchmeId>
<Id>
<PrvtId>
<Othr>
<Id>XXXXXXXXX</Id>
<SchmeNm>
<Prtry>SEPA</Prtry>
</SchmeNm>
</Othr>
</PrvtId>
</Id>
</CdtrSchmeId>
<DrctDbtTxInf>
<PmtId>
<InstrId>XXXXXXXXX</InstrId>
<EndToEndId>XXXXXXXXX</EndToEndId>
</PmtId>
<InstdAmt Ccy="EUR">136.82</InstdAmt>
<DrctDbtTx>
<MndtRltdInf>
<MndtId>XXXXXXXXX</MndtId>
<DtOfSgntr>2009-10-31</DtOfSgntr>
<AmdmntInd>false</AmdmntInd>
<AmdmntInfDtls>
<AmdmntInd>yellowland</AmdmntInd>
<OrgnlMndtId>XXXXXXXXX</OrgnlMndtId>
<OrgnlCdtrSchmeId>
<Id>
<PrvtId>
<Othr>
<Id>XXXXXXXXX</Id>
<SchmeNm>
<Prtry>SEPA</Prtry>
</SchmeNm>
</Othr>
</PrvtId>
</Id>
</OrgnlCdtrSchmeId>
</AmdmntInfDtls>
</MndtRltdInf>
</DrctDbtTx>
<DbtrAgt>
<FinInstnId>
<BIC>XXXXXXXXX</BIC>
</FinInstnId>
</DbtrAgt>
<Dbtr>
<Nm>TEST</Nm>
<PstlAdr>
<Ctry>BE</Ctry>
<AdrLine>XXXXXXXXX</AdrLine>
<AdrLine>XXXXXXXXX</AdrLine>
</PstlAdr>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>XXXXXXXXX</IBAN>
</Id>
</DbtrAcct>
<RmtInf>
<Ustrd>test</Ustrd>
</RmtInf>
</DrctDbtTxInf>
</PmtInf>
</CstmrDrctDbtInitn>
</Document>
The LineInformations are not always loaded, when you load xml via XDocument.
You need to specify that you also want to load the LineInformation when you load the XML. That is done by using one of the Load methods that you can pass in a value of LoadOptions of the XDocument class.
var document = XDocument.Load(file, LoadOptions.SetLineInfo);
From here
XDocument xdoc = XDocument.Load(file);
IEnumerable<XElement> nodes = xdoc.Descendants("nodeName");
foreach (XElement node in nodes)
{
IXmlLineInfo info = node;
int lineNumber = info.LineNumber;
}

Select subset of XML

I know this is a very basic question but I'm new to XML and while it seems simple, I can't find a simple answer anywhere. I have an XML document that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<root version="1">
<targets>
<target type="email">
<property name="to">b1q23#email.com</property>
</target>
<target type="fob"/>
</targets>
<observation uniqueID="00A60D" deviceID="308610ea23">
<field name="field1">test1</field>
<field name="field2">test2</field>
</observation>
and I'm trying to either select a subset of that xml, or remove nodes, to get it pared down to:
<observation uniqueID="00A60D" deviceID="308610ea23">
<field name="attachments">
<string>1910.jpg</string>
</field>
<field name="field1">test1</field>
<field name="field2">test2</field>
</observation>
So that I can deserialize it into an object. Any help is greatly appreciated.
You can use XPath:
string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<root version=\"1\">" +
"<targets>" +
"<target type=\"email\">" +
"<property name=\"to\">b1q23#email.com</property>" +
"</target>" +
"<target type=\"fob\"/>" +
"</targets>" +
"<observation uniqueID=\"00A60D\" deviceID=\"308610ea23\">" +
"<field name=\"field1\">test1</field>" +
"<field name=\"field2\">test2</field>" +
"</observation>" +
"</root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlElement root = doc.DocumentElement;
var observationNode = root.SelectSingleNode("/root/observation");
var observationXml = observationNode.OuterXml;
Here is a XML to LINQ Version:
dynamic root= XElement.Load(dataStream).Descendants("root")
.Select(element => element.Value).ToArray();
This will give all the root element from the document.And you can access root
XElement root = XElement.Parse("<root version ..." // etc. to parse a string.
// Use XElement.Load to load a file.
var observations = root.Elements("observation");
It assumes one root (by definition) and possibly multiple observation elements.

how can append to xml

i have this xml.
<project>
<user>
<id>1</id>
<name>a</name>
</user>
<user>
<id>2</id>
<name>b</name>
</user>
</project>
now how can append a new element like this between element <project></project>
<user>
<id>3</id>
<name>c</name>
</user>
string xml =
#"<project>
<user>
<id>1</id>
<name>a</name>
</user>
<user>
<id>2</id>
<name>b</name>
</user>
</project>";
XElement x = XElement.Load(new StringReader(xml));
x.Add(new XElement("user", new XElement("id",3),new XElement("name","c") ));
string newXml = x.ToString();
If you mean using C# then probably the simplest way is to load the xml up into an XmlDocument object and then add a node representing the additional element.
e.g. something like:
string filePath = "original.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
XmlElement root = xmlDoc.DocumentElement;
XmlNode nodeToAdd = doc.CreateElement(XmlNodeType.Element, "user", null);
XmlNode idNode = doc.CreateElement(XmlNodeType.Element, "id", null);
idNode.InnerText = "1";
XmlNode nameNode = doc.CreateElement(XmlNodeType.Element, "name", null);
nameNode.InnerText = "a";
nodeToAdd.AppendChild(idNode);
nodeToAdd.AppendChild(nameNode);
root.AppendChild(nodeToAdd);
xmlDoc.Save(filePath); // Overwrite or replace with new file name
But you haven't said where the xml fragments are - in files/strings?
If you have the below XML file:
<CATALOG>
<CD>
<TITLE> ... </TITLE>
<ARTIST> ... </ARTIST>
<YEAR> ... </YEAR>
</CD>
</CATALOG>
and you have to add another <CD> node with all its child nodes:
using System.Xml; //use the xml library in C#
XmlDocument document = new XmlDocument(); //creating XML document
document.Load(#"pathOfXmlFile"); //load the xml file contents into the newly created document
XmlNode root = document.DocumentElement; //points to the root element (catalog)
XmlElement cd = document.CreateElement("CD"); // create a new node (CD)
XmlElement title = document.CreateElement("TITLE");
title.InnerXML = " ... "; //fill-in the title value
cd.AppendChild(title); // append title to cd
XmlElement artist = document.CreateElement("ARTIST");
artist.InnerXML = " ... ";
cd.AppendChild(artist);
XmlElement year = document.CreateElement("YEAR");
year.InnerXML = " ... ";
cd.AppendChild(year);
root.AppendChild(cd); // append cd to the root (catalog)
document.save(#"savePath");//save the document

Categories