XMLPort using namespace

VincentVincent Member Posts: 2
Hello,

has anyone got some experience with the XMLPorts provided bij Navision 4.0?

I'm trying to import an xml-file which has a namespace "xmlns:xsi" defined. The xmldocument looks something like:

<MyTest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
<MyElement>SomeValue</MyElement>
</MyTest>

When I try to import this document I always get the following error message from navision:
"The namespace http://www.w3.org/2001/XMLSchem-instance has not been defined at object".

This message can't be found using the debugger. Thus I presume that the database engine generates this error.


I also can't find a place to put the namespace in the XMLPort definition. Searching for a place to put the namespace in the XMLPort definition I also tried putting the namespace as an attribute of the element "MyTest". But that didn't help much.

Without the namespace the import works just fine.

Has anybody got some idea?
With Regards,

Vincent van der Tol
ICM Solutions

Comments

  • Mark_SMark_S Member Posts: 17
    Have you already found a solution to your problem, because i'm having the same problem ](*,)
    M Stunnenberg
    GAC Business Solutions B.V.
  • DenSterDenSter Member Posts: 8,305
    Did you try adding an attribute "xmlns:xsi" to your MyTest node in yuor XMLPort?
  • Mark_SMark_S Member Posts: 17
    that's not the problem ..
    Because in my case, i've got:

    <rss version="2.0" xmlns:content="[url]">

    I've found a work around for this problem.
    I replaced that line with one w/o the xmlns:content="" Attribute

    like this:
    [/url]
    FileWrite.CREATE('C:\file_fixed.xml');
    FileWrite.CREATEOUTSTREAM(StrWrite);
    
    IntCounter := 0;
    FileRead.OPEN('C:\file.xml');
    FileRead.CREATEINSTREAM(StrRead);
    WHILE NOT (StrRead.EOS()) DO
    BEGIN
      StrRead.READTEXT(Txt);
      IF IntCounter = 2 THEN
        StrWrite.WRITETEXT('<rss version="2.0">')
      ELSE
        StrWrite.WRITETEXT(Txt);
      StrWrite.WRITETEXT();
      IntCounter := IntCounter + 1;
    END;
    FileWrite.CLOSE();
    FileRead.CLOSE();
    

    IntCounter must be (in my case) 2 because it's ALWAYS on the 3rd line of the file. After running this you'll be able to import file_fixed.xml
    M Stunnenberg
    GAC Business Solutions B.V.
  • sbraninsbranin Member Posts: 18
    I too am having this problem and I am about to use the code shown to edit the xml file before importing it. However, I can't believe that there isn't a way to solve this with the XMLPort itself. Has anybody found any other solution to this problem?

    I have tried adding the namespace attributes in various ways to the XMLPort itself but nothing seems to work.
  • BackiBacki Member Posts: 5
    Hi all,
    you cannot use XML Files with Namespace in XML Ports.
    This is not working.
    (Don't ask me why.. I just know that it doesn't)

    (You have to remove this 1st)

    Yours
    Stephan
    Yours
    Stephan
  • DogmatikDogmatik Member Posts: 2
    This post seems to infer there is a way to use xml with namespaces in xmlports.... http://msmvps.com/blogs/kine/archive/2006/05/04/100357.aspx

    It links to an article in partnersource... https://mbs.microsoft.com/partnersource/documentation/howtoarticles/xmlportswebservices.htm?printpage=false

    Anyone care to share the knowledge with us non-partners?
  • girish.joshigirish.joshi Member Posts: 407
    You can load the xml into dom, then run a stylesheet against it to strip out the namespaces, and then run the new xml through your xml port.
  • hugohugo Member Posts: 1
    Dogmatik wrote:
    This post seems to infer there is a way to use xml with namespaces in xmlports.... http://msmvps.com/blogs/kine/archive/2006/05/04/100357.aspx

    It links to an article in partnersource... https://mbs.microsoft.com/partnersource/documentation/howtoarticles/xmlportswebservices.htm?printpage=false

    Anyone care to share the knowledge with us non-partners?

    Here you are... :)


    Overview:
    A web service is a programmatic interface for application to application communication through the internet. The communication protocol is based on XML documents. An XML document usually contains namespaces to qualify its element and attribute names. Both applications must support namespaces to communicate.

    XMLports in Navision can be used to generate XML documents and communicate with web services. But they do not support namespaces in version 4.00. A simple method is described in this article to get around this limitation.


    Technical:

    To communicate with a web service, XMLports in Navision need to send and receive XML documents containing namespaces.

    1. Sending XML documents

    In the XMLport, the TagType “Attribute” can be used to define XML namespaces.

    For example, add the following tag in an XMLport:

    TagName: xmlns
    TagType: Attribute
    SourceType: Text
    DataSource: xmlns1

    Add the following C/AL code line in the OnPreXMLport() trigger of the XMLport:

    xmlns1 := 'http://schemas.xmlsoap.org/soap/envelope/';

    2. Receiving XML documents

    Before processing an XML document with an XMLport, an XML stylesheet can be applied to remove namespaces. An XML stylesheet contains a language for transforming XML documents into other XML documents.

    For example, the following procedure can be used in Navision:

    RemoveNamespace(
    XMLSourceDocument : Automation "'Microsoft XML, v4.0'.DOMDocument40";
    VAR XMLDestinationDocument : Automation "'Microsoft XML, v4.0'.DOMDocument40")

    TempTable."BLOB Field".CREATEOUTSTREAM(OutStreamStylesheet);
    TempTable."BLOB Field".CREATEINSTREAM(InStreamStylesheet);
    OutStreamStylesheet.WRITETEXT('<?xml version="1.0" encoding="UTF-8"?>');
    OutStreamStylesheet.WRITETEXT('<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">');
    OutStreamStylesheet.WRITETEXT('<xsl:output method="xml" encoding="UTF-8" />');
    OutStreamStylesheet.WRITETEXT('<xsl:template match="/">');
    OutStreamStylesheet.WRITETEXT('<xsl:copy>');
    OutStreamStylesheet.WRITETEXT('<xsl:apply-templates />');
    OutStreamStylesheet.WRITETEXT('</xsl:copy>');
    OutStreamStylesheet.WRITETEXT('</xsl:template>');
    OutStreamStylesheet.WRITETEXT('<xsl:template match="*">');
    OutStreamStylesheet.WRITETEXT('<xsl:element name="{local-name()}">');
    OutStreamStylesheet.WRITETEXT('<xsl:apply-templates select="@* | node()" />');
    OutStreamStylesheet.WRITETEXT('</xsl:element>');
    OutStreamStylesheet.WRITETEXT('</xsl:template>');
    OutStreamStylesheet.WRITETEXT('<xsl:template match="@*&quot;>');
    OutStreamStylesheet.WRITETEXT('<xsl:attribute name="{local-name()}"><xsl:value-of select="."/></xsl:attribute>');
    OutStreamStylesheet.WRITETEXT('</xsl:template>');
    OutStreamStylesheet.WRITETEXT('<xsl:template match="text() | processing-instruction() | comment()">');
    OutStreamStylesheet.WRITETEXT('<xsl:copy />');
    OutStreamStylesheet.WRITETEXT('</xsl:template>');
    OutStreamStylesheet.WRITETEXT('</xsl:stylesheet>');
    IF ISCLEAR(XMLStyleSheet) THEN
    CREATE(XMLStyleSheet);
    XMLStyleSheet.load(InStreamStylesheet);
    IF ISCLEAR(XMLDestinationDocument) THEN
    CREATE(XMLDestinationDocument);
    XMLSourceDocument.transformNodeToObject(XMLStyleSheet,XMLDestinationDocument);

    Add the following C/AL Locals in the procedure:

    TempTable: Record
    OutStreamStylesheet: OutStream
    InStreamStylesheet: InStream
    XMLStyleSheet: Automation "'Microsoft XML, v4.0'.DOMDocument40"
  • gupta.lalitgupta.lalit Member Posts: 6
    if this code is from a partner source then it should work but i cant get one thing:
    "How do we give reference to the source xml file and where will the final xml file be generated"

    Does anybody has any knowledge reagarding this?
  • pavelvonpavelvon Member Posts: 1
    if this code is from a partner source then it should work but i cant get one thing:
    "How do we give reference to the source xml file and where will the final xml file be generated"

    Does anybody has any knowledge reagarding this?

    Hi gupta.lalit
    I had the same problem like everybody in this thread. I laboured a bit and find a possible way. Here is the solution with the Microsoft function that I use :
    1. I have a form to fire the xmlPort.IMPORT

    FILE example :
    <DSKurz xmlns="http://tempuri.org/DSKurz.xsd"&gt;
    <kurz>
    <MENA>AUD</MENA>
    <OD>2007-01-01T00:00:00+01:00</OD>
    <DO>2999-12-31T23:59:59.997+01:00</DO>
    <KURZ> 16.299</KURZ>
    <POCET> 1</POCET>
    <MIN_PLATN>2007-01-30T00:00:00+01:00</MIN_PLATN>
    </kurz>

    2. I put the Microsoft fcn to this form (I assume that you didn't have problem to implement it...)

    3. The Code which fires the IMPORT is following :

    XMLDocInput is 'Microsoft XML, v4.0'.DOMDocument40
    XMLDocOut is 'Microsoft XML, v4.0'.DOMDocument40
    DialogMgt is CU Common Dialog Management

    // user chooses the xmlfile
    ImportFileName := DialogMgt.OpenFile(ImpTitle,'',4,'XML (*.xml)|*.xml',0);

    IF ImportFileName <> '' THEN BEGIN

    // preparing the import xml document
    IF ISCLEAR(XMLDocInput) THEN
    CREATE(XMLDocInput);

    XmlFile.OPEN(ImportFileName);
    XmlFile.CREATEINSTREAM(XmlInStr);

    // loading the import xml into the the XMLDOM
    XMLDocInput.load(XmlInStr);
    XmlFile.CLOSE;

    // calling the Microsoft function
    RemoveNamespace(XMLDocInput,XMLDocOut);

    // Overwriting the import file with the transformed one
    XMLDocOut.save(ImportFileName);

    // Processing the transformed file the standard way
    // Note, I use still the same file, however you can change the
    // code, that you can save it to different one
    XmlFile.OPEN(ImportFileName);
    XmlFile.CREATEINSTREAM(XmlInStr);
    XmlPortRateIn.SETSOURCE(XmlInStr);
    XmlPortRateIn.IMPORT;

    // clearing of course
    XmlFile.CLOSE;
    CLEAR(XMLDocOut);
    CLEAR(XMLDocInput);

    END;

    Hopefully this will help you :wink:

    One more add:
    I found usefull, that you may keep the original file #-o , or you just simly don't have permissions to write [-X (most common).
    You can change the code following way

    ...
    RemoveNamespace(XMLDocInput,XMLDocOut);
    TempImportTable.RESET;
    TempImportTable.DELETEALL;
    TempImportTable.Picture.CREATEOUTSTREAM(OutStrChangedFile);
    TempImportTable.Picture.CREATEINSTREAM(InStrChangedFile);

    XMLDocOut.save(OutStrChangedFile);
    XmlPortRateIn.SETSOURCE(InStrChangedFile);
    XmlPortRateIn.IMPORT;
    ...

    The benefi is simple, you don't need to write to disk at all,
    Enjoy !!! :lol:
  • gupta.lalitgupta.lalit Member Posts: 6
    Thanx pavelvon for your reply.
    Can u also tell me that what is the datatype and value of the following variables:

    1) ImportFileName
    2) ImpTitle
    3)

    // user chooses the xmlfile
    ImportFileName := DialogMgt.OpenFile(ImpTitle,'',4,'XML (*.xml)|*.xml',0);

    //
    can you tell me what is 'XML(*.xml)|*.xml',0)'

    4) XMLPortRateIn
    5) TempImportTable
    6) OutStrChangedFile
    7) InStrChangedFile
    8 ) TempTable - In RemovingNamespace function
  • maschmasch Member Posts: 8
    Of course I'm not pavelvon but I will give you the datatypes I used:

    1) ImportFileName type: Text1024
    2) ImpTitle type:Text250
    3) in this way you can set the filter (only XML-Files) in the Dialog Box
    4) XMLPortRateIn type: XMLPort <your XML-Port>
    5) TempImportTable type: Record (any table with a blob field, e.g. Table 27), property Temporary=Yes
    6) OutStrChangedFile type: OutStream
    7) InStrChangedFile type: InStream
    8 ) see 5)

    Hope this will help you.
    I did it in this way - and it works fine
  • svensk.tigersvensk.tiger Member Posts: 31
    I use a simple solution to remove the namespace from an xml file.
    This has an advantage, if you have to read avery large file, that eats up your memory by using XMLDOM and BLOB, because it only reads 4 lines max.
    Globals:
    Name			Type 
    ------------------------------------------------------------- 
    XMLfile			file 
    NamespaceFound	bool 
    Readsize			int 
    ReadCount			int 
    FileSize			int 
    Pos			 		int 
    Readline			Text 250 
    FilePath			Text 250, holds the name of the XML-File 
    InStreamOBJ		InStream 
    
    // Remove Namespace attribute from XML-File, because it is not supported by Nav 4.2.
    NamespaceFound := FALSE;
    Readsize := 0;
    ReadCount := 0;
    XMLfile.TEXTMODE := TRUE;
    XMLfile.OPEN(Filepath);
    Filesize := XMLfile.LEN;
    REPEAT
          readcount += 1;
          Readsize += (XMLfile.READ(Readline) + 2);                // Bytes in record + 2 Byte CRLF
          Pos := STRPOS(Readline,'xmlns');                         // Position of xmlns tag in record
          IF Pos > 0 THEN 
             NamespaceFound := TRUE;
          
    UNTIL (NamespaceFound = TRUE) OR                               // Stop reading, if namspace found
          (Readcount > 4) or                                       // Stop reading, if more than 4 records read
          (Readsize >= Filesize);                                  // Stop reading at end of file
    XMLfile.CLOSE;
    
    if NamespaceFound then begin
       XMLfile.WRITEMODE := TRUE;                                 // Reopen XML file in write mode and overwrite namespace
       XMLfile.OPEN(Filepath);                                    // tag by nonsence attribute of same length.
       XMLfile.SEEK(Readsize - STRLEN(Readline) - 2 + Pos - 1);   // position write pointer at 'xmlns'
       //                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/sdnList.xsd">
       XMLfile.WRITE(padstr('NoNameSpace="True - weil Navision das nicht kann, dieser Text muss die gleiche Laenge haben',
                             strlen(readline) - (pos -1) - 2) +'">');
       XMLfile.CLOSE;
       XMLfile.WRITEMODE := FALSE;
    end;
    
    
    // Import XML-Datei SDN.xml
    XMLfile.OPEN(Filepath);
    XMLfile.CREATEINSTREAM(InStreamOBJ);
    XMLPORT.IMPORT(75001, InStreamOBJ);
    XMLfile.CLOSE;
    
    The XMLport has to be modified, to reflect the new attribute:
    
    Tagname                  Tagtype  SourceType
    ---------------------------------------------
    sdnlist                  Element     Text
      NoNameSpace            Attribute  Text
    
    
    XML-File to read:
    ---------------------
    
    <?xml version="1.0" standalone="yes"?>
    <sdnList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/sdnList.xsd">
      <publshInformation>
        <Publish_Date>03/07/2007</Publish_Date>
        <Record_Count>3316</Record_Count>
      </publshInformation>
    
    XML-File after modification:
    --------------------------------- 
    <?xml version="1.0" standalone="yes"?>
    <sdnList NoNameSpace="True - weil Navision das nicht kann, dieser Text muss die gleiche Laenge haben">
      <publshInformation>
        <Publish_Date>03/07/2007</Publish_Date>
        <Record_Count>3316</Record_Count>
      </publshInformation>
    
    


    Sorry, looks a bit wild. Does anyone know, how to keep tabstops?
    Svensk.Tiger (Henning Möller)
    PASS Multibank Solutions AG
    (Kaum macht man was richtig, schon geht es. / Once you do it right, suddenly it works.)
  • KisuKisu Member Posts: 381
    Dogmatik wrote:
    This post seems to infer there is a way to use xml with namespaces in xmlports.... http://msmvps.com/blogs/kine/archive/2006/05/04/100357.aspx

    It links to an article in partnersource... https://mbs.microsoft.com/partnersource/documentation/howtoarticles/xmlportswebservices.htm?printpage=false

    Anyone care to share the knowledge with us non-partners?


    This does not work properly with some ocasions!

    like if you have following headers in xml file:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE Finvoice SYSTEM "Finvoice.dtd">
    <?xml-stylesheet type="text/xsl" href="Finvoice.xsl"?>
    <!--Finvoice xmlns:xsi="http://www.w3.org/2001/XMLScema-instance&quot; xsi:noNamespaceSchemaLocation="c:/l/finvoice/finvoice.xsd"Version="1.2"-->
    <Finvoice Version="1.2">...the rest of the file

    if you run this through that remove namespaces function it clears the whole xml file leaving the new file 0KB, but if you leave that <!DOCTYPE Finvoice SYSTEM "Finvoice.dtd"> part out, it does not do anything for the file.

    Is there any way I could clean the headings up to the first tag of the file?
    K.S.
  • KisuKisu Member Posts: 381
    Hmm and how could I strip that so it would have only those 2 headers:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <?xml-stylesheet type="text/xsl" href="Finvoice.xsl"?>
    <Finvoice Version="1.2">... the rest of the file

    as this way the importing would work and I could use the xsl file for formating it.
    K.S.
Sign In or Register to comment.