Skip to content

Commit 456bbc1

Browse files
committed
imp: readding validateAgainstDtds function
1 parent a722eb8 commit 456bbc1

File tree

3 files changed

+170
-98
lines changed

3 files changed

+170
-98
lines changed

libxml.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Napi::Object Libxml::Init(Napi::Env env, Napi::Object exports)
1515
InstanceMethod("loadXml", &Libxml::loadXml),
1616
InstanceMethod("loadXmlFromString", &Libxml::loadXmlFromString),
1717
InstanceMethod("loadDtds", &Libxml::loadDtds),
18+
InstanceMethod("validateAgainstDtds", &Libxml::validateAgainstDtds),
1819
InstanceMethod("getDtd", &Libxml::getDtd),
1920
InstanceMethod("freeXml", &Libxml::freeXml),
2021
InstanceMethod("freeDtds", &Libxml::freeDtds)
@@ -161,6 +162,77 @@ Napi::Value Libxml::loadDtds(const Napi::CallbackInfo& info) {
161162
return env.Undefined();
162163
}
163164

165+
Napi::Value Libxml::validateAgainstDtds(const Napi::CallbackInfo& info) {
166+
Napi::Env env = info.Env();
167+
168+
if(this->dtdsPaths.empty()){
169+
return env.Null();
170+
}
171+
172+
// if first param is number then apply it. If not then silently drop it
173+
if(info.Length() > 0 && info[0].IsNumber()) {
174+
XmlSyntaxError::ChangeMaxNumberOfError(info[0].ToNumber());
175+
}
176+
177+
//Setting context of validation
178+
bool oneOfTheDtdValidate = false;
179+
string dtdValidateName;
180+
181+
182+
//If length 0, return null; to implement
183+
Napi::Object errorsValidations = Napi::Object::New(env);
184+
185+
for (vector<xmlDtdPtr>::iterator dtd = this->dtdsPaths.begin(); dtd != this->dtdsPaths.end() ; ++dtd){
186+
const char* dtdName = (const char *)(*dtd)->SystemID;
187+
188+
//set up error handling
189+
Napi::Array errors = Napi::Array::New(env);
190+
xmlResetLastError();
191+
XmlSyntaxError::env = &env;
192+
xmlSetStructuredErrorFunc(reinterpret_cast<void*>(&errors),
193+
XmlSyntaxError::PushToArray);
194+
195+
Napi::String SystemIDString = Napi::String::New(env, dtdName);
196+
// Context creation for validation
197+
xmlValidCtxtPtr vctxt;
198+
if ((vctxt = xmlNewValidCtxt()) == nullptr) {
199+
continue;
200+
}
201+
//Instead we could set this to disable output : xmlSetStructuredErrorFunc(vctxt,errorsHandler);
202+
//xmlSetStructuredErrorFunc(vctxt, nullptr);
203+
204+
vctxt->userData = nullptr;
205+
vctxt->error = nullptr;
206+
vctxt->warning = nullptr;
207+
208+
// Validation
209+
int result = xmlValidateDtd(vctxt, this->docPtr, *dtd);
210+
211+
// drop error handling function and free context
212+
xmlSetStructuredErrorFunc(nullptr, nullptr);
213+
xmlFreeValidCtxt(vctxt);
214+
//If validation was successfull than break the loop
215+
if(result != 0){
216+
oneOfTheDtdValidate = true;
217+
dtdValidateName = dtdName;
218+
break;
219+
}
220+
// If validation failed add result to error object
221+
errorsValidations.Set(SystemIDString, errors);
222+
}
223+
if(oneOfTheDtdValidate){
224+
this->Value().Delete("validationDtdErrors");
225+
if(dtdValidateName.length()){
226+
return Napi::String::New(env, dtdValidateName);
227+
}else{
228+
return Napi::Boolean::New(env, true);
229+
}
230+
}else{
231+
this->Value().Set("validationDtdErrors", errorsValidations);
232+
return Napi::Boolean::New(env, false);
233+
}
234+
}
235+
164236
Napi::Value Libxml::getDtd(const Napi::CallbackInfo& info) {
165237
Napi::Env env = info.Env();
166238
Napi::HandleScope scope(env);

libxml.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Libxml : public Napi::ObjectWrap<Libxml>
4343
Napi::Value loadDtds(const Napi::CallbackInfo& info);
4444
// // static Napi::Value loadDtdsFromString(const Napi::CallbackInfo& info);
4545
// static Napi::Value loadSchemas(const Napi::CallbackInfo& info);
46-
// static Napi::Value validateAgainstDtds(const Napi::CallbackInfo& info);
46+
Napi::Value validateAgainstDtds(const Napi::CallbackInfo& info);
4747
// static Napi::Value validateAgainstSchemas(const Napi::CallbackInfo& info);
4848
// static Napi::Value xpathSelect(const Napi::CallbackInfo& info);
4949
Napi::Value getDtd(const Napi::CallbackInfo& info);

test/libxml-test.js

Lines changed: 97 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ describe('Node-Libxml', function () {
1515
libxml.freeDtds();
1616
});
1717
// Wellformed & valid
18-
// it('Should return wellformed & valid on a wellformed & valid xml', function () {
19-
// let libxml = new Libxml();
20-
// let testDefaultWf = libxml.loadXml('test/data/test-default.xml');
21-
// libxml.loadDtds(['test/dtd/mydoctype.dtd']);
22-
// let testDefaultV = libxml.validateAgainstDtds();
23-
// expect(testDefaultWf).to.be.true;
24-
// expect(testDefaultV).to.be.a('string');
25-
// libxml.freeXml();
26-
// libxml.freeDtds();
27-
// });
18+
it('Should return wellformed & valid on a wellformed & valid xml', function () {
19+
let libxml = new Libxml();
20+
let testDefaultWf = libxml.loadXml('test/data/test-default.xml');
21+
libxml.loadDtds(['test/dtd/mydoctype.dtd']);
22+
let testDefaultV = libxml.validateAgainstDtds();
23+
expect(testDefaultWf).to.be.true;
24+
expect(testDefaultV).to.be.a('string');
25+
libxml.freeXml();
26+
libxml.freeDtds();
27+
});
2828
// // it('Should return wellformed & valid on a wellformed & valid xml From String', function () {
2929
// // let libxml = new Libxml();
3030
// // let testDefaultStr = fs.readFileSync('test/data/test-default.xml','utf8');
@@ -59,42 +59,42 @@ describe('Node-Libxml', function () {
5959
expect(libxml).not.have.property("wellFormedErrors");
6060
libxml.freeXml();
6161
});
62-
// // Wellformed & invalid
63-
// it('Should return wellformed & invalid on a wellformed BUT invalid xml', function () {
64-
// let libxml = new Libxml();
65-
// let testInvalidWf = libxml.loadXml('test/data/test-not-valid-dtd.xml');
66-
// libxml.loadDtds(['test/dtd/mydoctype.dtd']);
67-
// let testInvalid = libxml.validateAgainstDtds(3);
68-
// expect(testInvalidWf).to.be.true;
69-
// expect(testInvalid).to.be.false;
70-
// expect(libxml).to.have.property('validationDtdErrors');
71-
// expect(libxml.validationDtdErrors).to.be.an('object');
72-
// expect(libxml.validationDtdErrors['test/dtd/mydoctype.dtd'].length).to.be.equal(3);
73-
// libxml.freeDtds();
74-
// libxml.freeXml();
75-
// });
76-
// it('Should return wellformed & invalid on a wellformed BUT invalid xml FROM STRING XML', function () {
77-
// let libxml = new Libxml();
78-
// let testInvalidWfStr = fs.readFileSync('test/data/test-not-valid-dtd.xml');
79-
// let testInvalidWf = libxml.loadXmlFromString(testInvalidWfStr);
80-
// libxml.loadDtds(['test/dtd/mydoctype.dtd']);
81-
// let testInvalid = libxml.validateAgainstDtds(3);
82-
// expect(testInvalidWf).to.be.true;
83-
// expect(testInvalid).to.be.false;
84-
// expect(libxml).to.have.property('validationDtdErrors');
85-
// expect(libxml.validationDtdErrors).to.be.an('object');
86-
// expect(libxml.validationDtdErrors['test/dtd/mydoctype.dtd'].length).to.be.equal(3);
87-
// libxml.freeDtds();
88-
// libxml.freeXml();
89-
// });
62+
// Wellformed & invalid
63+
it('Should return wellformed & invalid on a wellformed BUT invalid xml', function () {
64+
let libxml = new Libxml();
65+
let testInvalidWf = libxml.loadXml('test/data/test-not-valid-dtd.xml');
66+
libxml.loadDtds(['test/dtd/mydoctype.dtd']);
67+
let testInvalid = libxml.validateAgainstDtds(3);
68+
expect(testInvalidWf).to.be.true;
69+
expect(testInvalid).to.be.false;
70+
expect(libxml).to.have.property('validationDtdErrors');
71+
expect(libxml.validationDtdErrors).to.be.an('object');
72+
expect(libxml.validationDtdErrors['test/dtd/mydoctype.dtd'].length).to.be.equal(3);
73+
libxml.freeDtds();
74+
libxml.freeXml();
75+
});
76+
it('Should return wellformed & invalid on a wellformed BUT invalid xml FROM STRING XML', function () {
77+
let libxml = new Libxml();
78+
let testInvalidWfStr = fs.readFileSync('test/data/test-not-valid-dtd.xml', 'utf8');
79+
let testInvalidWf = libxml.loadXmlFromString(testInvalidWfStr);
80+
libxml.loadDtds(['test/dtd/mydoctype.dtd']);
81+
let testInvalid = libxml.validateAgainstDtds(3);
82+
expect(testInvalidWf).to.be.true;
83+
expect(testInvalid).to.be.false;
84+
expect(libxml).to.have.property('validationDtdErrors');
85+
expect(libxml.validationDtdErrors).to.be.an('object');
86+
expect(libxml.validationDtdErrors['test/dtd/mydoctype.dtd'].length).to.be.equal(3);
87+
libxml.freeDtds();
88+
libxml.freeXml();
89+
});
9090
// not wellformed
9191
it('Should return Not Wellformed & invalid on a not wellformed xml', function () {
9292
let libxml = new Libxml();
9393
let wellformed = libxml.loadXml('test/data/test-not-wellformed.xml');
94-
// libxml.loadDtds(['test/dtd/mydoctype.dtd']);
95-
// let wellformedV = libxml.validateAgainstDtds();
94+
libxml.loadDtds(['test/dtd/mydoctype.dtd']);
95+
let wellformedV = libxml.validateAgainstDtds();
9696
expect(wellformed).to.be.false;
97-
// expect(wellformedV).to.be.false;
97+
expect(wellformedV).to.be.false;
9898
expect(libxml).to.have.property('wellformedErrors');
9999
expect(libxml.wellformedErrors).to.be.an('array');
100100
libxml.freeXml();
@@ -142,62 +142,62 @@ describe('Node-Libxml', function () {
142142
// libxml.freeXml();
143143
// });
144144
// // // ABOVE IS ALL THE SAME WITH MEMORY MANUAL MANADGEMENT
145-
// it('should free XML memory & infos when asked in manual mod On not wellformed xml', function () {
146-
// let libxml = new Libxml(true);
147-
// let wellformed = libxml.loadXml('test/data/test-not-wellformed.xml');
148-
// expect(wellformed).to.be.false;
149-
// expect(libxml).to.have.property('wellformedErrors');
150-
// expect(libxml.wellformedErrors).to.be.an('array');
151-
// expect(libxml.wellformedErrors.length).to.be.at.least(1);
152-
// libxml.freeXml();
153-
// expect(libxml).not.to.have.property('wellformedErrors');
154-
// });
155-
// it('should not crash when freeUp memory xml multiple time!', function () {
156-
// let libxml = new Libxml(true);
157-
// let wellFormed = libxml.loadXml('test/data/test-default.xml');
158-
// expect(wellFormed).to.be.true;
159-
// expect(libxml).not.to.have.property('wellformedErrors');
160-
// libxml.freeXml();
161-
// libxml.freeXml();
162-
// libxml.freeXml();
163-
// expect(libxml).not.to.have.property('wellformedErrors');
164-
// });
165-
// it('Should return intended values after multiple CLEAN!', function () {
166-
// let libxml = new Libxml();
167-
// let wellformed = libxml.loadXml('test/data/test-not-valid-dtd.xml');
168-
// libxml.loadDtds(['test/dtd/mydoctype.dtd']);
169-
// let wellformedV = libxml.validateAgainstDtds();
170-
// expect(wellformed).to.be.true;
171-
// expect(wellformedV).to.be.false;
172-
// expect(libxml).to.not.have.property('wellformedErrors');
173-
// libxml.freeXml();
174-
// libxml.freeDtds();
175-
// libxml.freeDtds();
176-
// wellformed = libxml.loadXml('test/data/test-default.xml');
177-
// libxml.loadDtds(['test/dtd/mydoctype.dtd', 'test/dtd/myBADdoctype.dtd']);
178-
// wellformedV = libxml.validateAgainstDtds();
179-
// expect(wellformed).to.be.true;
180-
// expect(wellformedV).to.be.a('string');
181-
// expect(wellformedV).to.be.equal('test/dtd/mydoctype.dtd');
182-
// expect(libxml).to.not.have.property('wellformedErrors');
183-
// });
184-
// it('should not crash when loads multiple dtd it two times', function () {
185-
// let libxml = new Libxml();
186-
// let wellformed = libxml.loadXml('test/data/test-not-valid-dtd.xml');
187-
// libxml.loadDtds(['test/dtd/mydoctype.dtd', 'test/dtd/myBADdoctype.dtd']);
188-
// libxml.loadDtds(['test/dtd/mydoctype2.dtd', 'test/dtd/myBADdoctype2.dtd']);
189-
// let wellformedV = libxml.validateAgainstDtds();
190-
// expect(wellformed).to.be.true;
191-
// expect(wellformedV).to.be.false;
192-
// expect(libxml).to.not.have.property('wellformedErrors');
193-
// expect(libxml).to.have.property('validationDtdErrors');
194-
// expect(libxml.validationDtdErrors).to.have.property('test/dtd/mydoctype.dtd');
195-
// expect(libxml.validationDtdErrors).to.have.property('test/dtd/mydoctype2.dtd');
196-
// expect(libxml.validationDtdErrors).to.have.property('test/dtd/mydoctype2.dtd');
197-
// expect(libxml.validationDtdErrors).to.have.property('test/dtd/myBADdoctype2.dtd');
198-
// libxml.freeXml();
199-
// libxml.freeDtds();
200-
// });
145+
it('should free XML memory & infos when asked in manual mod On not wellformed xml', function () {
146+
let libxml = new Libxml(true);
147+
let wellformed = libxml.loadXml('test/data/test-not-wellformed.xml');
148+
expect(wellformed).to.be.false;
149+
expect(libxml).to.have.property('wellformedErrors');
150+
expect(libxml.wellformedErrors).to.be.an('array');
151+
expect(libxml.wellformedErrors.length).to.be.at.least(1);
152+
libxml.freeXml();
153+
expect(libxml).not.to.have.property('wellformedErrors');
154+
});
155+
it('should not crash when freeUp memory xml multiple time!', function () {
156+
let libxml = new Libxml(true);
157+
let wellFormed = libxml.loadXml('test/data/test-default.xml');
158+
expect(wellFormed).to.be.true;
159+
expect(libxml).not.to.have.property('wellformedErrors');
160+
libxml.freeXml();
161+
libxml.freeXml();
162+
libxml.freeXml();
163+
expect(libxml).not.to.have.property('wellformedErrors');
164+
});
165+
it('Should return intended values after multiple CLEAN!', function () {
166+
let libxml = new Libxml();
167+
let wellformed = libxml.loadXml('test/data/test-not-valid-dtd.xml');
168+
libxml.loadDtds(['test/dtd/mydoctype.dtd']);
169+
let wellformedV = libxml.validateAgainstDtds();
170+
expect(wellformed).to.be.true;
171+
expect(wellformedV).to.be.false;
172+
expect(libxml).to.not.have.property('wellformedErrors');
173+
libxml.freeXml();
174+
libxml.freeDtds();
175+
libxml.freeDtds();
176+
wellformed = libxml.loadXml('test/data/test-default.xml');
177+
libxml.loadDtds(['test/dtd/mydoctype.dtd', 'test/dtd/myBADdoctype.dtd']);
178+
wellformedV = libxml.validateAgainstDtds();
179+
expect(wellformed).to.be.true;
180+
expect(wellformedV).to.be.a('string');
181+
expect(wellformedV).to.be.equal('test/dtd/mydoctype.dtd');
182+
expect(libxml).to.not.have.property('wellformedErrors');
183+
});
184+
it('should not crash when loads multiple dtd in two rounds', function () {
185+
let libxml = new Libxml();
186+
let wellformed = libxml.loadXml('test/data/test-not-valid-dtd.xml');
187+
libxml.loadDtds(['test/dtd/mydoctype.dtd', 'test/dtd/myBADdoctype.dtd']);
188+
libxml.loadDtds(['test/dtd/mydoctype2.dtd', 'test/dtd/myBADdoctype2.dtd']);
189+
let wellformedV = libxml.validateAgainstDtds();
190+
expect(wellformed).to.be.true;
191+
expect(wellformedV).to.be.false;
192+
expect(libxml).to.not.have.property('wellformedErrors');
193+
expect(libxml).to.have.property('validationDtdErrors');
194+
expect(libxml.validationDtdErrors).to.have.property('test/dtd/mydoctype.dtd');
195+
expect(libxml.validationDtdErrors).to.have.property('test/dtd/myBADdoctype.dtd');
196+
expect(libxml.validationDtdErrors).to.have.property('test/dtd/mydoctype2.dtd');
197+
expect(libxml.validationDtdErrors).to.have.property('test/dtd/myBADdoctype2.dtd');
198+
libxml.freeXml();
199+
libxml.freeDtds();
200+
});
201201
// // SCHEMAS
202202
// it('Should return wellformed & valid on a wellformed & valid xml SCHEMA', function () {
203203
// let libxml = new Libxml();

0 commit comments

Comments
 (0)