I'm currently working on some software which trawls some proprietary data and generates an XML document according to a specified DTD. So far so good. Now, I'm very keen on actually testing what I produce, and the first step I'd like to do is to check that the generated XML validates against the DTD. I have installed XML Unit, which has an "assertXMLValid" method for just this task. Except I can't get it to work. My XML looks like:
and I have placed the DTD in the file 'BTNB_TimeRecording.dtd' in the "current directory". I'm not at liberty to mess with the generated XML. However, every time I try and do anything with my generated XML, I get an error: Relative URI "BTNB_TimeRecording.dtd"; can not be resolved without a base URI Now I know that most parsers are smart enough to look in the same location as the XML file for a DTD, but how am I supposed to validate some XML in a freshly generated String against a provided DTD? Is there a way of globally telling a parser to try looking in the current directory for DTDs? Or is there some way of "preloading" a parser with one or more DTDs so it doesn't need to look "outside" at all? Or am I misunderstanding things so much that I simply can't see what I should be doing? All help appreciated, thanks.
Unless you can find a "setEntityResolver()" method from the XMLUnit API, I'd simply write my own validation assert method, which - Obtains a DocumentBuilder with validation turned on - Gives the DocumentBuilder an EntityResolver implementation which reads the DTD file from wherever your test wants it to - Parses a given XML string and return a false if the parse() method throws an exception
Thanks Lasse, I'm not quite sure what you mean by the stuff about passing in an EntityResolver (and I'm even less sure where I would find or make such a thing) but I don't think this will actually solve my problem anyway. I have now found that the assertXMLValid method that I am calling, can be passed a "systemId" parameter, It seems strange, but if I pass it a string containing exactly the same filename as in the DTD, it now works (I won't ask why - I certainly don't understand at the moment!) But, this now shows up another problem. Any further code which tries to load/parse this XML now complains with the same "base URI" error, and not all of the methods have a "systemId" parameter. I honestly can't see why I should need to pass in the filename every time, anyway - it's right there in the XML file if only the parser knew where to look. I have a growing feeling that there's something big and obvious that I'm just missing. Although I've worked with XML quite a lot, I've never had to worry about DTDs up until now, and I'm finding it surprisingly troublesome What's the point of needing to put the DTD in the XML document, if you also need to tell a parser where each DTD is every time you do anything? Surely there must be something analogous to a "classpath" in Java, some sort of "look here for any DTDs" setting. The error message teases by mentioning the concept of a "base URI", which sounds just what I need - except that I can't find any useful references to the term anywhere else.