Skip to content

Commit cb91422

Browse files
committed
Adding possibility to load XML via string
1 parent 7f37b5f commit cb91422

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed

Readme.md

+9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ It can perform:
99
- Validity against DTD/XSD(Schema) check,
1010
- Get doctype informations (about dtd)
1111
- GetXpath Values
12+
- Load XMl from string or file path
1213

1314
## Requirements:
1415

@@ -23,6 +24,7 @@ Node-libxml has been thought differently than [libxmljs](https://github.com/libx
2324
- You wan to validate against DTD (libxmljs can't)
2425
- You want a silent program if xml is not wellformed (node-libxml returns wellformed error in object; libxmljs throws)
2526
- You want to do xml processing in parallel forks
27+
- You want to load XML from file path OR string
2628
- You want to validate against DTD / schema on multiple documents with just ONE dtd/schema loaded in memory (libxmljs loads it on each validation request), so it's clearly by far fastest!
2729

2830

@@ -40,6 +42,8 @@ Node-libxml has been thought differently than [libxmljs](https://github.com/libx
4042
let libxml = new Libxml();
4143

4244
let xmlIsWellformed = libxml.loadXml('path/to/xml');
45+
let xmlIsWellformedStr = libxml.loadXmlFromString('<name>test</name>');
46+
4347
console.log(xmlIsWellformed);
4448
console.log(xmlIsWellformed.wellformedErrors);
4549

@@ -72,6 +76,11 @@ A function of libxml to load the XML file
7276
`TAKE a path & RETURN true if wellformed | false if not`
7377
`SET a an array 'wellformedErrors' in libxml element containing wellformed errors`
7478

79+
##### loadXmlFromString(string)
80+
A function of libxml to create the xml Dom from a string
81+
`TAKE a string containing xml & RETURN true if wellformed | false if not`
82+
`SET a an array 'wellformedErrors' in libxml element containing wellformed errors`
83+
7584

7685
##### loadDtds(array)
7786
A function of libxml to load the DTDs files

libxml.cpp

+84
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ NAN_MODULE_INIT(Libxml::Init) {
4141
tpl->InstanceTemplate()->SetInternalFieldCount(1);
4242

4343
Nan::SetPrototypeMethod(tpl, "loadXml", loadXml);
44+
Nan::SetPrototypeMethod(tpl, "loadXmlFromString", loadXmlFromString);
4445
Nan::SetPrototypeMethod(tpl, "loadDtds", loadDtds);
46+
// Nan::SetPrototypeMethod(tpl, "loadDtdsFromString", loadDtdsFromString);
4547
Nan::SetPrototypeMethod(tpl, "loadSchemas", loadSchemas);
4648
Nan::SetPrototypeMethod(tpl, "validateAgainstDtds", validateAgainstDtds);
4749
Nan::SetPrototypeMethod(tpl, "validateAgainstSchemas", validateAgainstSchemas);
@@ -102,6 +104,36 @@ NAN_METHOD(Libxml::loadXml) {
102104
}
103105
}
104106

107+
NAN_METHOD(Libxml::loadXmlFromString) {
108+
if (info.Length() < 1){
109+
return Nan::ThrowTypeError("loadXmlFromString requires at least 1 argument");
110+
}
111+
v8::Local<v8::Array> errors = Nan::New<v8::Array>();
112+
xmlResetLastError();
113+
xmlSetStructuredErrorFunc(reinterpret_cast<void *>(&errors),
114+
XmlSyntaxError::PushToArray);
115+
Libxml* libxml = Nan::ObjectWrap::Unwrap<Libxml>(info.Holder());
116+
String::Utf8Value str(info[0]->ToString());
117+
string txt (*str);
118+
// Those options shoudl be send by the user, it enable/disbale errors, warnings ..
119+
int options;
120+
options = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
121+
if(libxml->docPtr != NULL){
122+
xmlFreeDoc(libxml->docPtr);
123+
libxml->docPtr = nullptr;
124+
}
125+
libxml->docPtr = xmlReadMemory(txt.c_str(), txt.length(), NULL, NULL, options);
126+
xmlSetStructuredErrorFunc(NULL, NULL);
127+
128+
if(libxml->docPtr == NULL){
129+
// We set property to libxml element only if notWellformed
130+
info.Holder()->Set(Nan::New<v8::String>("wellformedErrors").ToLocalChecked(), errors);
131+
info.GetReturnValue().Set(Nan::False());
132+
}else{
133+
info.GetReturnValue().Set(Nan::True());
134+
}
135+
}
136+
105137
NAN_METHOD(Libxml::getDtd){
106138
Nan::HandleScope scope;
107139
Libxml* libxml = Nan::ObjectWrap::Unwrap<Libxml>(info.Holder());
@@ -173,6 +205,58 @@ NAN_METHOD(Libxml::loadDtds){
173205
}
174206
}
175207

208+
// NAN_METHOD(Libxml::loadDtdsFromString){
209+
// if (info.Length() < 1){
210+
// return Nan::ThrowTypeError("loadDtds requires at least 1 argument, an array of DTDs");
211+
// }
212+
// if(!info[0]->IsArray()){
213+
// return Nan::ThrowTypeError("loadDtds requires an array");
214+
// }
215+
// Nan::EscapableHandleScope scope;
216+
// Libxml* libxml = Nan::ObjectWrap::Unwrap<Libxml>(info.Holder());
217+
// Local<Array> dtdsStrLocal = Local<Array>::Cast(info[0]);
218+
// Local<Array> errors = Nan::New<Array>();
219+
// int options;
220+
// options = (XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
221+
// // disbale errors erreurs etc
222+
// //v8::Local<v8::Array> errorsDTD = Nan::New<v8::Array>();
223+
// xmlResetLastError();
224+
// xmlSetStructuredErrorFunc(reinterpret_cast<void *>(&errors),
225+
// XmlSyntaxError::PushToArray);
226+
// for (unsigned int i = 0; i < dtdsStrLocal->Length(); i++){
227+
// if (Nan::Has(dtdsStrLocal, i).FromJust() && Nan::Get(dtdsStrLocal, i).ToLocalChecked()->IsString()) {
228+
// Local<String> value = Nan::Get(dtdsStrLocal, i).ToLocalChecked()->ToString();
229+
// String::Utf8Value strV8(value->ToString());
230+
// string pathStr (*strV8);
231+
// xmlDocPtr dtdDoc = xmlReadMemory(pathStr.c_str(),pathStr.length(),NULL,NULL,options);;
232+
// if (dtdDoc == NULL) {
233+
// //DTD is bad, we set error and not assign it + next
234+
// errors->Set(i, Nan::New<String>(pathStr.c_str()).ToLocalChecked());
235+
// continue;
236+
// }
237+
// // Parse DTD from memory
238+
// xmlParserInputBufferPtr dtdBuf = xmlParserInputBufferCreateMem(pathStr.c_str(), pathStr.size(),
239+
// XML_CHAR_ENCODING_UTF8);
240+
// if (!dtdBuf) {
241+
// errors->Set(i, Nan::New<String>(pathStr.c_str()).ToLocalChecked());
242+
// continue;
243+
// }
244+
// xmlDtdPtr pDtd = xmlIOParseDTD(NULL, dtdBuf, XML_CHAR_ENCODING_UTF8);
245+
// if (pDtd == NULL) {
246+
// xmlFreeDtd(pDtd);
247+
// errors->Set(i, Nan::New<String>(pathStr.c_str()).ToLocalChecked());
248+
// continue;
249+
// }
250+
// libxml->dtdsPaths.push_back(pDtd);
251+
// }
252+
// }
253+
// xmlSetStructuredErrorFunc(NULL, NULL);
254+
// // We set dtdsLoadedErrors property for js side
255+
// if(errors->Length()){
256+
// info.Holder()->Set(Nan::New<v8::String>("dtdsLoadedErrors").ToLocalChecked(), errors);
257+
// }
258+
// }
259+
176260
NAN_METHOD(Libxml::loadSchemas){
177261
if (info.Length() < 1){
178262
return Nan::ThrowTypeError("loadSchemas requires at least 1 argument, an array of Schemas");

libxml.h

+2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ class Libxml : public Nan::ObjectWrap {
4040

4141
static NAN_METHOD(New);
4242
static NAN_METHOD(loadXml);
43+
static NAN_METHOD(loadXmlFromString);
4344
static NAN_METHOD(loadDtds);
45+
// static NAN_METHOD(loadDtdsFromString);
4446
static NAN_METHOD(loadSchemas);
4547
static NAN_METHOD(validateAgainstDtds);
4648
static NAN_METHOD(validateAgainstSchemas);

test/libxml-test.js

+41
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const Libxml = require('../index.js');
44
const expect = require('chai').expect;
5+
const fs = require('fs');
56

67
describe('Node-Libxml', function () {
78
it('Should return a list of errored path if dtd path is bad', function () {
@@ -24,12 +25,38 @@ describe('Node-Libxml', function () {
2425
libxml.freeXml();
2526
libxml.freeDtds();
2627
});
28+
// it('Should return wellformed & valid on a wellformed & valid xml From String', function () {
29+
// let libxml = new Libxml();
30+
// let testDefaultStr = fs.readFileSync('test/data/test-default.xml','utf8');
31+
// let myDtd = "<!ELEMENT xpath (to)>\n" +
32+
// "<!ELEMENT to (my)>\n" +
33+
// "<!ELEMENT my (infos,infosdust)>\n" +
34+
// "<!ATTLIST infos\n" +
35+
// "xmlns CDATA #FIXED ''\n" +
36+
// "attrib NMTOKEN #IMPLIED>\n" +
37+
// "<!ELEMENT infos (#PCDATA)>\n" +
38+
// "<!ELEMENT infosdust (#PCDATA)>";
39+
// let testDefaultWf = libxml.loadXmlFromString(testDefaultStr);
40+
// libxml.loadDtdsFromString([myDtd]);
41+
// let testDefaultV = libxml.validateAgainstDtds();
42+
// expect(testDefaultWf).to.be.true;
43+
// expect(testDefaultV).to.be.a('string');
44+
// libxml.freeXml();
45+
// libxml.freeDtds();
46+
// });
2747
it('should return wellformed on a wellformed XMl in utf8-bom & other encoding', function () {
2848
let libxml = new Libxml();
2949
let testNotUtf8 = libxml.loadXml('test/data/test-default-not-utf8.xml');
3050
expect(testNotUtf8).to.be.true
3151
libxml.freeXml();
3252
});
53+
it('should return wellformed on a wellformed XMl in utf8-bom & other encoding FROM STRING', function () {
54+
let libxml = new Libxml();
55+
let defaultNotUtf8 = fs.readFileSync('test/data/test-default-not-utf8.xml','utf8');
56+
let testNotUtf8 = libxml.loadXmlFromString(defaultNotUtf8);
57+
expect(testNotUtf8).to.be.true;
58+
libxml.freeXml();
59+
});
3360
// Wellformed & invalid
3461
it('Should return wellformed & invalid on a wellformed BUT invalid xml', function () {
3562
let libxml = new Libxml();
@@ -44,6 +71,20 @@ describe('Node-Libxml', function () {
4471
libxml.freeDtds();
4572
libxml.freeXml();
4673
});
74+
it('Should return wellformed & invalid on a wellformed BUT invalid xml FROM STRING XML', function () {
75+
let libxml = new Libxml();
76+
let testInvalidWfStr = fs.readFileSync('test/data/test-not-valid-dtd.xml');
77+
let testInvalidWf = libxml.loadXmlFromString(testInvalidWfStr);
78+
libxml.loadDtds(['test/dtd/mydoctype.dtd']);
79+
let testInvalid = libxml.validateAgainstDtds(3);
80+
expect(testInvalidWf).to.be.true;
81+
expect(testInvalid).to.be.false;
82+
expect(libxml).to.have.property('validationDtdErrors');
83+
expect(libxml.validationDtdErrors).to.be.an('object');
84+
expect(libxml.validationDtdErrors['test/dtd/mydoctype.dtd'].length).to.be.equal(3);
85+
libxml.freeDtds();
86+
libxml.freeXml();
87+
});
4788
// not wellformed
4889
it('Should return Not Wellformed & invalid on a not wellformed xml', function () {
4990
let libxml = new Libxml();

0 commit comments

Comments
 (0)