@@ -183,40 +183,55 @@ En primer lugar, si queremos que la validación se lleve a cabo debemos añadir:
183183 factory. setValidating(true );
184184
185185 Otro aspecto importante es el de la manipulación de la validación, que se lleva
186- cabo definiendo un \" *resolutor de entidades *\" .
186+ a cabo definiendo un *resolutor de entidades *.
187187
188188.. code-block :: java
189- : emphasize- lines: 1 ,13 ,14 ,27
190-
191- builder. setEntityResolver(new EntityResolver2 () {
192- @Override
193- public InputSource getExternalSubset (String name , String baseURI ) {
194- return null ;
195- }
196-
197- @Override
198- public InputSource resolveEntity (String publicID , String systemID ) throws SAXException , IOException {
199- return resolveEntity(null , publicID, null , systemID);
200- }
201-
202- @Override
203- public InputSource resolveEntity (String name , String publicID , String baseURI , String systemID )
204- throws SAXException , IOException {
205- if (systemID == null ) return null ;
206-
207- try {
208- if (! new URI (systemID). isAbsolute()) {
209- // Se supone que "ruta" ya se definió como Path.
210- systemID = ruta. getParent(). resolve(systemID). toString();
211- }
212- }
213- catch (URISyntaxException err) {
214- return null ;
215- }
216-
217- return new InputSource (systemID);
218- }
219- });
189+ : emphasize- lines: 1 ,3 ,4 ,9 ,10 ,15 ,16
190+
191+ builder. setEntityResolver(new EntityResolver2 () {
192+ @Override
193+ public InputSource getExternalSubset (String name , String baseURI )
194+ throws SAXException , IOException {
195+ return null ;
196+ }
197+
198+ @Override
199+ public InputSource resolveEntity (String publicId , String systemId )
200+ throws SAXException , IOException {
201+ return resolveEntity(null , publicId, null , systemId);
202+ }
203+
204+ @Override
205+ public InputSource resolveEntity (String name , String publicId , String baseURI , String systemId )
206+ throws SAXException , IOException {
207+
208+ if (systemId == null ) return null ;
209+
210+ try {
211+ systemId = resolvePath(baseURI, systemId);
212+ } catch (URISyntaxException e) {
213+ return null ;
214+ }
215+
216+ return new InputSource (systemId);
217+ }
218+
219+ private String resolvePath (String base , String path ) throws URISyntaxException {
220+ if (new URI (path). isAbsolute()) return path;
221+ if (base == null ) throw new IllegalArgumentException (" No puede calcularse una ruta relativa si la base es nula." );
222+
223+ if (base. contains(" !" )) {
224+ // Nos quedamos con la parte del path dentro del jar
225+ Path basePath = Path . of(base. substring(base. indexOf(" !" ) + 1 ));
226+ // Resolvemos el path relativo y devolvemos el recurso.
227+ URL resource = getClass(). getResource(basePath. resolveSibling(path). toString());
228+ return resource != null ? resource. toString() : null ;
229+ }
230+
231+ return new URI (base). resolve(path). toString();
232+ }
233+
234+ });
220235
221236 Debemos fijarnos en el último método. Cuando devuelve `null `, es como, si no
222237hubiéramos definido nada, y el procesador obrará como lo hace habitualmente para
@@ -227,25 +242,27 @@ original.
227242
228243.. admonition :: Advertencia
229244
230- El código incluye una variable ``ruta ``, que es un objeto |Path | que
231- contiene la ruta del archivo |XML | en consonancia con :ref: `el ejemplo
232- ilustrativo que escribimos sobre lectura <jaxp-read>`.
245+ Este código da por hecho que se conoce la ruta del |XML | (``baseURI ``). Esto,
246+ sin embargo, puede ser cierto o no. Todo este procesamiento lo desencadena
247+ :code: `builder.parse() `, el cual permite proporcionar los datos de distinto
248+ modo. Puede pasarse un |String | o un |File | en cuyo caso
249+ sí se sabrá ``baseURI ``. En cambio, si se pasa un |InputStream | (que es
250+ *precisamente la forma en la que hemos ilustrado el uso *) no hay modo de
251+ conocer su valor y, en consencuencia, será ``null ``. Eso sí, en este último
252+ caso, se admite un segundo argumento con una cadena que defina ``baseURI ``.
233253
234- Si en cambio, ``ruta `` fuera una objeto :java-net: `URI <URI> ` podríamos obtener la cadena
235- con la ruta del |DTD | de este otro modo:
236-
237- .. code-block :: java
254+ ¿Qué hace exactamente el código que hemos propuesto? En principio, si
255+ no hay definido ningun |DTD |, no hace nada. En cambio, si hay definido uno,
256+ comprueba si el |DTD | se proporciona con ruta absoluta. Si es así, respeta el
257+ valor y la validación se hará con el valor expresado en el archivo. En cambio,
258+ si la ruta es relativa, hace una distinción:
238259
239- systemID = ruta. resolve(systemID). toString();
260+ * Si ``baseURI `` contiene el carácter ``! `` se ha pasado como |XML | un
261+ :ref: `archivo de recursos <file-arc-pro >` y en consecuencia el |DTD | también
262+ lo será y hay que buscarlo dentro del paquete |JAR |.
240263
241- ¿Qué hace exactamente el código que hemos propuesto? En principio, si
242- no hay definido ninguno, no hace nada. En cambio, si hay definido uno,
243- comprueba si el |DTD | se proporcionó con ruta absoluta (lo cual incluye una
244- |URL | completa). Si fue así, respeta el valor y la validación se hará con el
245- valor expresado en el archivo. En cambio, si la ruta era relativa, hay un
246- problema: la librería entiende la ruta relativa no respecto al |XML | (que sería
247- lo esperable), sino respecto al directorio de trabajo. Lo que hace nuestro
248- código en este caso, es hacerla relativa respecto al |XML |.
264+ * Si no es así, se resuelve de forma normal la ruta relativa usando como base el
265+ |XML | (``baseURI ``).
249266
250267.. tip :: El argumento del constructor de `InputSource` también puede ser un
251268 :java-io: `Reader <Reader> `, así que si nuestra intención es que el programa no
@@ -386,6 +403,7 @@ si nuestra intención es usarla una sola vez:
386403.. |DTD | replace :: :abbr: `DTD ( Document Type Definition ) `
387404.. |JDK | replace :: :abbr: `JDK ( Java Development Kit ) `
388405.. |URL | replace :: :abbr: `URL ( Uniform Resource Locator ) `
406+ .. |JAR | replace :: :abbr: `JAR ( Java ARchive ) `
389407
390408.. |Node | replace :: :java-jaxp: `Node `
391409.. |Element | replace :: :java-jaxp: `Element `
@@ -395,3 +413,6 @@ si nuestra intención es usarla una sola vez:
395413.. |NamedNodeMap | replace :: :java-jaxp: `NamedNodeMap `
396414.. |Document | replace :: :java-jaxp: `Document `
397415.. |Path | replace :: :java-nio: `Path `
416+ .. |String | replace :: :java-io: `String <String> `
417+ .. |InputStream | replace :: :java-io: `InputStream <InputStream> `
418+ .. |File | replace :: :java-io: `File <File> `
0 commit comments