VALIDATION XML
Best Answer
-
Try using TryValidateAgainstSchema method from "Xml Validation" Codeunit and let us know what is the problem that you cannot deal with, so we might be able to help.1
Answers
-
You can try to work with newly XML data types for XML added.Thanks
Blog - rockwithnav.wordpress.com/
Twitter - https://twitter.com/RockwithNav
Facebook - https://facebook.com/rockwithnav/0 -
RockWithNAV wrote: »You can try to work with newly XML data types for XML added.
0 -
Try using TryValidateAgainstSchema method from "Xml Validation" Codeunit and let us know what is the problem that you cannot deal with, so we might be able to help.1
-
Unfortunately I still have a problem. It seems that in my case the validation of the file does not depend on a single xsd file but on multiple files recalled from the main xsd file. Only one xsd file can be passed as an argument when calling the TryValidateAgainstSchema function. In the onprem version we have no difficulty as we can pass the path that contains the files. With the onCloud target this is not possible0
-
That is true, you cannot specify more than one schema, unfortunately.
Look into this module on github: XMLValidation
I think that you could easily extend that by implementing new external procedure "AddSchema" and I think that XmlDoc DotNet can handle it.
You would need to open the Pull Request in this repository and someone from Microsoft team would have to review it. After that it would be available OnCloud too.0 -
Thank you. I take this opportunity to ask you if there is a function that deletes empty nodes in an XML. I took a look but I don't seem to find anything0
-
I am not aware of ready-made function, but I would try something like the code below. Didn't test it though, but I bet you get the idea.
procedure RemoveEmptyNodes(var XDoc: XmlDocument) var XNode: XmlNode; XElement: XmlElement; begin foreach XNode in XDoc.GetDescendantElements() do begin XElement := XNode.AsXmlElement(); if not (XElement.HasElements() or XElement.HasAttributes() or not XElement.IsEmpty()) then XElement.Remove(); end; end;
0 -
I am not aware of ready-made function, but I would try something like the code below. Didn't test it though, but I bet you get the idea.
procedure RemoveEmptyNodes(var XDoc: XmlDocument) var XNode: XmlNode; XElement: XmlElement; begin foreach XNode in XDoc.GetDescendantElements() do begin XElement := XNode.AsXmlElement(); if not (XElement.HasElements() or XElement.HasAttributes() or not XElement.IsEmpty()) then XElement.Remove(); end; end;
I tried to use your code but I have some problems. Fails to instruction xmlDoc.WriteTo(OutStream);. The error is of a technical nature without description:trigger OnAction() var TempBlob: Codeunit "Temp Blob"; Filename: Text[250]; fileMgt: Codeunit "File Management"; InStream: InStream; OutStream: OutStream; InStream2: InStream; xmlDoc: XmlDocument; XNode: XmlNode; XElement: XmlElement; begin fileName := fileMgt.BLOBImportWithFilter(tempBlob, 'Choose XML', fileName, 'XML Files (*.XML)|*.XML', 'xml'); if fileName <> '' then begin tempBlob.CreateInStream(InStream); TempBlob.CreateOutStream(OutStream); if XmlDocument.ReadFrom(InStream, xmlDoc) then begin foreach XNode in xmlDoc.GetDescendantElements() do begin XElement := XNode.AsXmlElement(); if (not XElement.HasElements()) or (NOT XElement.HasAttributes()) or (XElement.IsEmpty()) then begin XElement.Remove(); xmlDoc.WriteTo(OutStream); end end end; Filename := 'XmlFileTest.xml'; DownloadFromStream(InStream, '', '', '', Filename); end; end;
0 -
The problem is that you are executing the following line
xmlDoc.WriteTo(OutStream);
as many times as many XmlElements there is in the XmlDocument.
Try moving it right after this loop ends.
0 -
Your if statement is wrong. In that form you should change or to and operators.
I just noticed that XmlElement.IsEmpty() doesn't behave as expected. It is always true.
Try this instead:if not (XElement.HasElements() or XElement.HasAttributes() or (XElement.InnerText() <> '')) then XElement.Remove();
It should be working.0 -
My problem however occurs when I write the changes to the file using.
xmlDoc.WriteTo(OutStream);
0 -
Please show me your code again, because it seems to work for me.0
-
Please show me your code again, because it seems to work for me.
trigger OnAction() var TempBlob: Codeunit "Temp Blob"; Filename: Text[250]; fileMgt: Codeunit "File Management"; InStream: InStream; OutStream: OutStream; InStream2: InStream; xmlDoc: XmlDocument; XNode: XmlNode; XElement: XmlElement; begin fileName := fileMgt.BLOBImportWithFilter(tempBlob, 'Choose XML', fileName, 'XML Files (*.XML)|*.XML', 'xml'); if fileName <> '' then begin tempBlob.CreateInStream(InStream); TempBlob.CreateOutStream(OutStream); if XmlDocument.ReadFrom(InStream, xmlDoc) then begin foreach XNode in xmlDoc.GetDescendantElements() do begin XElement := XNode.AsXmlElement(); if (not XElement.HasElements()) or (NOT XElement.HasAttributes()) or (XElement.IsEmpty()) then begin XElement.Remove(); end end end; xmlDoc.WriteTo(OutStream); Filename := 'XmlFileTest.xml'; DownloadFromStream(InStream, '', '', '', Filename); end; end;
0 -
As I said, your IF statement is wrong, so you are removing elements that cannot be removed, because the XML file would be broken.
Please replace this line with the line from my previous comment, which isif not (XElement.HasElements() or XElement.HasAttributes() or (XElement.InnerText() <> '')) then XElement.Remove();
0 -
Ok. Error was skipped but empty elements remain
0 -
It is because there is something weird with XmlElement.IsEmpty().
I thought that checking the XmlElement.InnerText() will do the thing, but maybe not all the cases?0 -
Ok. Error was skipped but empty elements remain
I've just checked and that example works fine for me. Are you sure we're on the same page here?local procedure ImportXMLAndRemoveEmptyNodes() var FileManagement: Codeunit "File Management"; TempBlob: Codeunit "Temp Blob"; Filename: Text; InStream: InStream; OutStream: OutStream; XDocument: XmlDocument; begin Filename := FileManagement.BLOBImportWithFilter(TempBlob, 'Choose XML', FileName, 'XML Files (*.XML)|*.XML', 'xml'); if FileName <> '' then begin TempBlob.CreateInStream(InStream); TempBlob.CreateOutStream(OutStream); if XmlDocument.ReadFrom(InStream, XDocument) then RemoveEmptyNodes(XDocument); XDocument.WriteTo(OutStream); end; Filename := 'XmlFileTest.xml'; DownloadFromStream(InStream, '', '', '', Filename); end; local procedure RemoveEmptyNodes(var XDoc: XmlDocument) var XNode: XmlNode; XElement: XmlElement; begin foreach XNode in XDoc.GetDescendantElements() do begin XElement := XNode.AsXmlElement(); if not (XElement.HasElements() or XElement.HasAttributes() or (XElement.InnerText() <> '')) then XElement.Remove(); end; end;
I am executing procedure ImportXMLAndRemoveEmptyNodes() OnAction trigger.
Have you changed the conditionnot XmlElement.IsEmpty()
toXmlElement.InnerText <> 0
?0 -
Hi Dreez,
I have reported exactly the code above and the result is that the <Fax /> node is not deleted from the file although it is empty.0 -
I've solved problem.
This is my code:trigger OnAction() var FileManagement: Codeunit "File Management"; TempBlob: Codeunit "Temp Blob"; Filename: Text; InStream: InStream; OutStream: OutStream; XDocument: XmlDocument; begin Filename := FileManagement.BLOBImportWithFilter(TempBlob, 'Choose XML', FileName, 'XML Files (*.XML)|*.XML', 'xml'); if FileName <> '' then begin TempBlob.CreateInStream(InStream); if XmlDocument.ReadFrom(InStream, XDocument) then begin RemoveEmptyNodes(XDocument); Clear(TempBlob); TempBlob.CreateInStream(InStream); TempBlob.CreateOutStream(OutStream); XDocument.WriteTo(OutStream); Filename := 'XmlFileTest.xml'; DownloadFromStream(InStream, '', '', '', Filename); end end; end; local procedure RemoveEmptyNodes(var XDoc: XmlDocument) var XNode: XmlNode; XElement: XmlElement; Valore: Text; cr: Char; lf: char; begin cr := 13; lf := 10; foreach XNode in XDoc.GetDescendantElements() do begin XElement := XNode.AsXmlElement(); Valore := delchr(XElement.InnerText(), '=', ' '); valore := DELCHR(valore, '=', FORMAT(cr)); valore := DELCHR(valore, '=', FORMAT(lf)); if Valore = '' then XElement.Remove(); end; end;
0 -
So now I've a strange result. XML File processed remove empty node ma leave carriage return. This is an example:
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<Root>
<Customer>
<No>01121212</No>
<Name>Spotsmeyer's Furnishings</Name>
<city>Miami</city>
</Customer>
<Customer>
<No>01445544</No>
<Name>Progressive Home Furnishings</Name>
<city>Chicago</city>
<condizioni>
<code>3060</code>
<description>30, 60 giorni</description>
</condizioni>
</Customer>
</Root>
There is a way to remove also end of line (cr char)?0 -
Following this, as I also had this issue with IsEmpty.
I went through the nodelist backwards to also remove a potential parent, whose child elements have all been removed. Otherwise you can still end up with empty Elements.0 -
How did you do it? can you show me how to build the code?0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions