Malformed XML parser lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- gicla · 2018-02-06 22:57 Help me please! I surfed the web for days but I could not find any help or code examples about how to parse a so called "malformed" XML file. I have to read nodes in a log file in which there are messages XML style but without root node. This is an example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 000241230 0002412300ApprovedCurrently I'm using: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ReadXMLFile(Doc, fs);ParsingNodes := Doc.GetElementsByTagName('Request');But it's working only if I add root element to the log file before to open it. Any help will be appreciated. ---------------------------------------------------------------------- molly · 2018-02-07 00:10 Quote from: gicla on February 06, 2018, 11:57:50 pmBut it's working only if I add root element to the log file before to open it. You would still have to add the root-node manually because XML will still need to be valid  Here is another way to accomplish that: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   RootNode := Doc.CreateElement('root');  Doc.AppendChild(RootNode);  ReadXMLFragment(RootNode, 'data.xml');   ParsingNodes := Doc.GetElementsByTagName('Request'); ---------------------------------------------------------------------- gicla · 2018-02-07 10:11 Thanks molly, your hint it's perfectly working with the xml in my previous example. Problem now is that the real xml I'm going to read is slightly different, it has a declaration and looks like the following: Code: XML  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 2018-01-30 10:30:43,862 INFO  [Transaction-1] [REQUEST  ] message:[000241< /Seq>230Not Approved]2018-01-30 10:30:43,862 INFO  [Transaction-3] [REQUEST  ] message:[00024123< /Type>00Approved] When trying to open it, the command ReadXMLFragment generate the following error: "XML declaration is not allowed here". Is there any parameter I can set in order for the ReadXMLFragment command to ignore the XML declaration? This is the current piece of code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  I: Integer;  fs: TFileStream;  PassNode: TDOMNode;  Doc: TXMLDocument;  ParsingNodes: TDOMNodeList; begin  if OpenDialog1.Execute then    begin      fs := nil;      fs := TFileStream.Create(Utf8ToAnsi(OpenDialog1.FileName), fmOpenRead or fmShareDenyNone);       Doc := TXMLDocument.Create;      PassNode := Doc.CreateElement('root');      Doc.AppendChild(PassNode);      ReadXMLFragment(PassNode, fs);                        <-- LINE GENERATING THE ERROR      ParsingNodes := Doc.GetElementsByTagName('TransactionResponse'); //seleziona solo responses       for I := 0 to doc.DocumentElement.GetChildCount - 1 do        begin //          ... anything I want to do with the XML ...        end;    end;end; Thanks in advance! ---------------------------------------------------------------------- Cyrax · 2018-02-07 19:08 Quote from: gicla on February 07, 2018, 11:11:07 amThanks molly, your hint it's perfectly working with the xml in my previous example. Problem now is that the real xml I'm going to read is slightly different, it has a declaration and looks like the following: Code: XML  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 2018-01-30 10:30:43,862 INFO  [Transaction-1] [REQUEST  ] message:[000241< /Seq>230Not Approved]2018-01-30 10:30:43,862 INFO  [Transaction-3] [REQUEST  ] message:[00024123< /Type>00Approved] When trying to open it, the command ReadXMLFragment generate the following error: "XML declaration is not allowed here". Is there any parameter I can set in order for the ReadXMLFragment command to ignore the XML declaration? You need to learn and use regular expression to extract the xml portion from the data. http://wiki.freepascal.org/Regexpr Quote from: gicla on February 07, 2018, 11:11:07 amThis is the current piece of code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  I: Integer;  fs: TFileStream;  PassNode: TDOMNode;  Doc: TXMLDocument;  ParsingNodes: TDOMNodeList; begin  if OpenDialog1.Execute then    begin      fs := nil;      fs := TFileStream.Create(Utf8ToAnsi(OpenDialog1.FileName), fmOpenRead or fmShareDenyNone);       Doc := TXMLDocument.Create;      PassNode := Doc.CreateElement('root');      Doc.AppendChild(PassNode);      ReadXMLFragment(PassNode, fs);                        <-- LINE GENERATING THE ERROR      ParsingNodes := Doc.GetElementsByTagName('TransactionResponse'); //seleziona solo responses       for I := 0 to doc.DocumentElement.GetChildCount - 1 do        begin //          ... anything I want to do with the XML ...        end;    end;end; Thanks in advance! ---------------------------------------------------------------------- molly · 2018-02-07 22:38 Quote from: gicla on February 07, 2018, 11:11:07 amProblem now is that the real xml I'm going to read is slightly different... Indeed, and alas, in that case the readXMLfragment is also not able to help you out there. If it was me, i would take a moment to think on what it is exactly that you wish to accomplish as there could be several approaches. First, it seems to me that your file is a log file. Each entry in that log is situated on a single line. Part of that line contains xml. What is it that you wish to accomplish with the data stored in the xml part (and what of the other information for that matter) ? Is your goal to end up with a single xml document that has each entry listed, so that you are able to query the xml document for those data that you need ? Or is it that the only reason to use xml parsing is because your data is stored in xml format, and that you do not care about that at all as long as you are able to extract the parts that you are interested in ? In case the former, you could perhaps use a stringlist for line parsing, use extractword (and related function) to break apart the line and store that into an xml document. In that case the xml tags would have to be removed/skipped/ignored/replaced. In case the latter then using a regular expressions might perhaps be more helpful, as suggested by user Cyrax (you could use regex for the former as well, but nothing a simple search and replace or extractword couldn't fix for you). Secondly, there is use of non compliant xml. You could perhaps solve that with using a on the fly xml parser (react to events) (perhaps better known as sax), but you have to take into account that in the end using a sax parser could perhaps not solve the reading/parsing for you either. Another possible approach could be to use benibela's internet tools I'm too inexperienced with xml (and mentioned approaches) to be able to give you a better advice atm. I was unable to solve it in a more easier manner, but perhaps other readers have an idea or two. ---------------------------------------------------------------------- gicla · 2018-02-07 23:50 Thanks a lot molly for your very detailed comments. I appreciated. At the end, if no better solution from other readers, I guess I will read the log file, search for and extract xml portions and store them in an array. Then I will validate every xml message one at a time picking them from the array. I'll update the post if succesful.