@@ -168,117 +168,6 @@ ejemplo, |Element|:
168168 devuelve el atributo (|Attr |) o el valor del atributo cuyo nombre se
169169 proporciona en el argumento.
170170
171- .. _jaxp-dtd :
172-
173- .. rubric :: Validación
174-
175- Hemos evitado validar el documento hasta ahora. Sin embargo, la validación puede
176- ser interesante o incluso, puede ser preciso, intentar que ni siquiera se haga
177- ninguna comprobación en caso de que la declaración exista, pero el |DTD | no.
178-
179- En primer lugar, si queremos que la validación se lleve a cabo debemos añadir:
180-
181- .. code-block :: java
182-
183- factory. setValidating(true );
184-
185- Otro aspecto importante es el de la manipulación de la validación, que se lleva
186- a cabo definiendo un *resolutor de entidades *.
187-
188- .. code-block :: java
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- });
235-
236- Debemos fijarnos en el último método. Cuando devuelve `null `, es como, si no
237- hubiéramos definido nada, y el procesador obrará como lo hace habitualmente para
238- llevar a cabo la validación. En cambio, si devolvemos un :code: `new
239- InputSource(cadena) ` utilizará el |DTD | que indique esa cadena (puede ser una
240- |URL | o un archivo local) con independencia de lo que expresase la declaración
241- original.
242-
243- .. admonition :: Advertencia
244-
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 ``.
253-
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:
259-
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 |.
263-
264- * Si no es así, se resuelve de forma normal la ruta relativa usando como base el
265- |XML | (``baseURI ``).
266-
267- .. tip :: El argumento del constructor de `InputSource` también puede ser un
268- :java-io: `Reader <Reader> `, así que si nuestra intención es que el programa no
269- escupa nunca un error (incluso aunque el |DTD | de la declaración no se
270- encuentre), podemos hacer hacer lo siguiente:
271-
272- .. code-block :: java
273-
274- @Override
275- public InputSource resolveEntity(String name, String publicID, String baseURI, String systemID)
276- throws SAXException , IOException {
277- return new InputSource (new StringReader (" " ));
278- }
279-
280- .. todo :: ¿Cómo forzar una validación, aunque no haya declaración DOCTYPE?
281-
282171.. _jaxp-write :
283172
284173Escritura
@@ -391,6 +280,82 @@ si nuestra intención es usarla una sola vez:
391280 int cantidad = ((Double ) xPath. evaluate(" count(//profesor)" , xml, XPathConstants . NUMBER )). intValue();
392281 System . out. println(cantidad);
393282
283+ .. _jaxp-dtd :
284+
285+ Validación
286+ ==========
287+ Hemos evitado validar el documento hasta ahora. Sin embargo, la validación puede
288+ ser interesante o incluso, puede ser preciso, intentar que ni siquiera se haga
289+ ninguna comprobación en caso de que la declaración exista, pero el |DTD | no.
290+
291+ En primer lugar, si queremos que la validación se lleve a cabo debemos añadir:
292+
293+ .. code-block :: java
294+
295+ factory. setValidating(true );
296+
297+ Otro aspecto importante es el de la manipulación de la validación, que se lleva
298+ a cabo definiendo un *resolutor de entidades *:
299+
300+ .. literalinclude :: files/MiEntityResolver.java
301+ :language: java
302+ :caption: MiEntityResolver.java
303+ :class: toggle
304+ :start-at: public class
305+
306+ Debemos fijarnos en el último método. Cuando devuelve `null `, es como, si no
307+ hubiéramos definido nada, y el procesador obrará como lo hace habitualmente para
308+ llevar a cabo la validación. En cambio, si devolvemos un :code: `new
309+ InputSource(cadena) ` utilizará el |DTD | que indique esa cadena (puede ser una
310+ |URL | o un archivo local) con independencia de lo que expresase la declaración
311+ original.
312+
313+ Definido, podremos usarlo en el *builder * antes de procesar el documento:
314+
315+ .. code-block :: java
316+
317+ builder. setEntityResolver(new MiEntityResolver ());
318+ Document xml = builder. parse(st);
319+
320+ .. admonition :: Advertencia
321+
322+ Este código da por hecho que se conoce la ruta del |XML | (``baseURI ``). Esto,
323+ sin embargo, puede ser cierto o no. Todo este procesamiento lo desencadena
324+ :code: `builder.parse() `, el cual permite proporcionar los datos de distinto
325+ modo. Puede pasarse un |String | o un |File | en cuyo caso
326+ sí se sabrá ``baseURI ``. En cambio, si se pasa un |InputStream | (que es
327+ *precisamente la forma en la que hemos ilustrado el uso *) no hay modo de
328+ conocer su valor y, en consencuencia, será ``null ``. Eso sí, en este último
329+ caso, se admite un segundo argumento con una cadena que defina ``baseURI ``.
330+
331+ ¿Qué hace exactamente el código que hemos propuesto? En principio, si
332+ no hay definido ningun |DTD |, no hace nada. En cambio, si hay definido uno,
333+ comprueba si el |DTD | se proporciona con ruta absoluta. Si es así, respeta el
334+ valor y la validación se hará con el valor expresado en el archivo. En cambio,
335+ si la ruta es relativa, hace una distinción:
336+
337+ * Si ``baseURI `` contiene el carácter ``! `` se ha pasado como |XML | un
338+ :ref: `archivo de recursos <file-arc-pro >` y en consecuencia el |DTD | también
339+ lo será y hay que buscarlo dentro del paquete |JAR |.
340+
341+ * Si no es así, se resuelve de forma normal la ruta relativa usando como base el
342+ |XML | (``baseURI ``).
343+
344+ .. tip :: El argumento del constructor de `InputSource` también puede ser un
345+ :java-io: `Reader <Reader> `, así que si nuestra intención es que el programa no
346+ escupa nunca un error (incluso aunque el |DTD | de la declaración no se
347+ encuentre), podemos hacer hacer lo siguiente:
348+
349+ .. code-block :: java
350+
351+ @Override
352+ public InputSource resolveEntity(String name, String publicID, String baseURI, String systemID)
353+ throws SAXException , IOException {
354+ return new InputSource (new StringReader (" " ));
355+ }
356+
357+ .. todo :: ¿Cómo forzar una validación, aunque no haya declaración DOCTYPE?
358+
394359.. rubric :: Notas al pie
395360
396361.. [# ] En realidad el método tiene sentido para otros nodos que no sean
0 commit comments