var url = "http://localhost:9000";
var file;
function preload(){
file = loadXML("filename,xml");
}
function setup(){
httpPost(url,"xml",file,success,failure);
}
function success(){}//some stuff to run when it is successful
function failure(){}// when an error is produced.
The error I get -
error
p5.js:59782 Uncaught (in promise) TypeError: Converting circular structure to JSON at JSON.stringify () at p5.httpDo (p5.js:59782) at p5.httpPost (p5.js:59634) at setup (sketch.js:20) at p5. (p5.js:46215) at _runIfPreloadsAreDone (p5.js:46163) at p5._decrementPreload (p5.js:46173) at p5.js:59339 at p5.js:59851
The XML file used -
ListLedgers.xml
<ENVELOPE>
<HEADER>
<VERSION>1</VERSION>
<TALLYREQUEST>Export</TALLYREQUEST>
<TYPE>Data</TYPE>
<ID>List of Ledgers</ID>
</HEADER>
<BODY>
<DESC>
<TDL>
<TDLMESSAGE>
<REPORT NAME="List of Ledgers" ISMODIFY="No" ISFIXED="No" ISINITIALIZE="No" ISOPTION="No" ISINTERNAL="No">
<FORMS>List of Ledgers</FORMS>
</REPORT>
<FORM NAME="List of Ledgers" ISMODIFY="No" ISFIXED="No" ISINITIALIZE="No" ISOPTION="No" ISINTERNAL="No">
<TOPPARTS>List of Ledgers</TOPPARTS>
<XMLTAG>"List of Ledgers"</XMLTAG>
</FORM>
<PART NAME="List of Ledgers" ISMODIFY="No" ISFIXED="No" ISINITIALIZE="No" ISOPTION="No" ISINTERNAL="No">
<TOPLINES>List of Ledgers</TOPLINES>
<REPEAT>List of Ledgers : Collection of Ledgers</REPEAT>
<SCROLLED>Vertical</SCROLLED>
</PART>
<LINE NAME="List of Ledgers" ISMODIFY="No" ISFIXED="No" ISINITIALIZE="No" ISOPTION="No" ISINTERNAL="No">
<LEFTFIELDS>List of Ledgers</LEFTFIELDS>
</LINE>
<FIELD NAME="List of Ledgers" ISMODIFY="No" ISFIXED="No" ISINITIALIZE="No" ISOPTION="No" ISINTERNAL="No">
<SET>$Name</SET>
<XMLTAG>"NAME"</XMLTAG>
</FIELD>
<COLLECTION NAME="Collection of Ledgers" ISMODIFY="No" ISFIXED="No" ISINITIALIZE="No" ISOPTION="No" ISINTERNAL="No">
<TYPE>Ledger</TYPE>
</COLLECTION>
</TDLMESSAGE>
</TDL>
</DESC>
</BODY>
</ENVELOPE>
What happens if you write
httpPost(url,"xml",file.getContent(),success,failure);
We can probably make this a bit user friendly so I'll open another issue about that if my suggestion works.
Doing this gives no error but it just posts this part to the server -
",1,Export,Data,List of Ledgers,List of Ledgers,List of Ledgers,"List of Ledgers",List of Ledgers,List of Ledgers : Collection of Ledgers,Vertical,List of Ledgers,$Name,"NAME",Ledger,"
instead of the actual XML file.
As a result, the server responses with an unknown request error.
The "datatype" parameter of httpPost is meant to define the return type of data from the server, the data to be sent to the server, httpPost itself should be able to infer its type and make the right decision on how to handle it. That being said, it only handles a few types for now: objects, strings and number values.
For objects, which include p5.XML (what loadXML returns), it simply pass it directly to JSON.stringify to be serialized into strings before it can be sent to the server. In this case, it probably detected self reference in the resulting p5.XML object or its children so it cannot stringify it.
file.getContent only returns the content of the specific tag referenced (or the whole XML), comma separated. It does not serialize the data properly nor include any attributes or tag names, etc.
To be able to use httpPost the way you are using it in your original example, we will need a couple things:
p5.XML which serializes the tags, contents and attributes as proper XML string. This I think will be rather useful in any case.httpPost will need to detect a p5.XML is passed as data and call the relevant function to serialize it into strings before proceeding.httpPost to include sending plain text string when passed as data parameter.I'm ok with adding all these features to httpPost but let's see if there's differing ideas.
How come we have a custom implementation of XML parsing and don't import one that is suitable instead? It's a big task to maintain all the code we have and I personally would like to outsource difficult code like XML parsing to a library focused on doing one thing very well.
We could wrap the library with some custom class if we want to maintain the current API.
@Zalastax The current implementation probably is a translation from Processing, including a custom implementation.
I think if the native DOMParser API is good enough for what we need, we can use that and if not then a lightweight library wouldn't be a bad idea either. However, anything heavier than that should at least wait until a build process with tree shaking is ready otherwise we risk adding too much dead code in the library.
Edit: Actually the library already uses DOMParser for the initial parsing, just the step to further parse the DOM object into p5.XML object requires custom code.
Glad to hear that we already use the DOMParser! So, if we modify p5.XML to work against a DOM Document (I'm guessing it's not represented as that already) we could both remove some code from the parser and get serialization for free via XMLSerializer?
As long as browsers behave alike I think that would be the neatest solution.
When it's working against a DOM we can pretty much assume they work cross browser similarly as we would work with it the same way as the main Document DOM and query it the same way. It would be nice if p5.XML is simply an abstraction for the DOM then we can easily extract the DOM to be passed to XMLSerializer.
As it is now we lose any underlying reference to the XML DOM when we parse to p5.XML which makes serializing it again more difficult than necessary. I'll have a look into this.
I tried using the loadStrings() function which worked perfectly fine with the httpPost method using the following code -
list = loadStrings("ListLedgers.xml");
function setup(){
list = list.join('');
httpPost(url,"xml",list,yay,oops);
}
@robotrobo That will work but you won't be able to manipulate the XML with p5.js before sending it off to the server.
Took a few days to get back here but I believe all functionality of p5.XML can be replaced with native DOM query API. If I get some time this week, I'll try implementing it.
Most helpful comment
@Zalastax The current implementation probably is a translation from Processing, including a custom implementation.
I think if the native DOMParser API is good enough for what we need, we can use that and if not then a lightweight library wouldn't be a bad idea either. However, anything heavier than that should at least wait until a build process with tree shaking is ready otherwise we risk adding too much dead code in the library.
Edit: Actually the library already uses DOMParser for the initial parsing, just the step to further parse the DOM object into p5.XML object requires custom code.