I need validate XML file schema using XSD file.
I'm using Business Central SaaS version and cannot use dotnet.
Searching I've found this article but on SaaS not work.
Someone can help me?
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.
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.
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.
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 possible
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.
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 anything
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 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;
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;
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.
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.
Answers
Blog - rockwithnav.wordpress.com/
Twitter - https://twitter.com/RockwithNav
Facebook - https://facebook.com/rockwithnav/
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.
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:
as many times as many XmlElements there is in the XmlDocument.
Try moving it right after this loop ends.
I've tried but same error..
I just noticed that XmlElement.IsEmpty() doesn't behave as expected. It is always true.
Try this instead:
It should be working.
Please replace this line with the line from my previous comment, which is
I thought that checking the XmlElement.InnerText() will do the thing, but maybe not all the cases?
I've just checked and that example works fine for me. Are you sure we're on the same page here?
I am executing procedure ImportXMLAndRemoveEmptyNodes() OnAction trigger.
Have you changed the condition to ?
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.
This is my code:
<?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)?
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.