J'ai une classe qui shareals XML à partir d'une source tierce (je n'ai aucun contrôle sur le contenu). Voici l'extrait que lesmurs: Le XML Je reçois contient un chemin relatif dans le doctype. Fondamentalement Ceci fonctionne avec succès en tant qu'application Java 1.5. Afin d'éviter l'erreur ci-dessus, je devais créer un répertoire ./dtd sur la racine du projet et inclure tous les fichiers DTD (pas sûr pourquoi je devais le faire, mais nous y arriverons). P> < P> J'ai depuis créé un service Web sur tomcat5.5 qui utilise la classe ci-dessus. Je reçois Question n ° 1: Où puis-je localiser ./dtd afin que la classe puisse le trouver lorsqu'elle est exécutée comme Web Tomcat Webservice? Y a-t-il une configuration Tomcat ou service que je dois faire pour que le répertoire reconnu? P> Question n ° 2: Pourquoi la classe a-t-elle même besoin du fichier DTD en premier lieu? N'a-t-elle pas toutes les informations dont il a besoin de lamarser dans les annotations de la classe DTD-> XSD->? J'ai lu de nombreux postes sur la validation de la validation, la définition d'entitésResource et d'autres solutions, mais cette classe n'est pas toujours déployée en tant que service Web et je ne veux pas avoir deux trains de code. P> P> connexions code> est une classe DTD-> xsd-> une classe générée par XJC. Le package
com.optimumirlightpath.it.aspenoss.xsd code> contient toutes ces classes. P>
str.value code> ci-dessus contient: p>
[org.xml.sax.saxparseException: uri relatif "./dtd/connections.dtd"; ne peut pas être résolu sans URI de document.] code> sur la ligne de lamairiste. J'ai essayé de créer ./dtd dans chaque dossier relavant (racine de projet, webcontent, Web-Inf, Dir du travail Tomcat, etc.) en vain. P>
3 Réponses :
question n ° 2: pourquoi la classe est-elle même Besoin du fichier DTD en premier lieu? P>
Ce n'est pas la mise en œuvre JAXB qui recherche la DTD, c'est l'analyseur sous-jacent. P>
question n ° 1: où puis-je localiser ./dtd afin que la classe puisse le trouver quand elle est courante comme un service Web Tomcat? P> blockQuote>
Je ne suis pas sûr, mais ci-dessous, je vais démontrer une façon de faire ce travail en utilisant le MOXY JAXB Mise en œuvre (je suis le plomb technique) qui fonctionnera dans plusieurs environnements. p>
solution proposée forte> P> Créez une entitéResolver qui charge la DTD de la classe de classe. De cette façon, vous pouvez emballer la DTD avec votre application et vous saurez toujours où il est indépendamment de l'environnement de déploiement. P>
xxx pré> puis à l'aide de la mise en œuvre MOXY JAXB que vous pouvez accomplir à la mise en œuvre sous-jacente et définir l'entitéresolver. p>
xxx pré> blockQquote>
Blaise - TY pour prendre le temps de répondre. Initialement, Jaxbhelper s'est plaint que le motard n'était pas un eclipselink Unmlarshaller. J'ai donc remplacé javax.xml.bind.jaxbcontext avec org.eclipse.persistence.jaxb.jaxbcontext et javax.xml.bind.unmarshaller avec org.eclipse.persistence.jaxb.jaxbunmarshaller. Cependant, l'Eclipselink JaxbContext renvoie un type Javax JaxbContext. Jaxbunmarshaller nécessite un type eclipselink et je me trompe d'exceptions si j'essaie de reposer. Des idées?
Vous devez ajouter un fichier nommé jaxb.properties dans avec vos classes de modèle avec l'entrée suivante: javax.xml.bind.context.factory = org.eclipse.persistence.jaxb. JaxbContextFactory
Je peux essayer cela à un autre moment. J'ai été capable de faire fonctionner la réponse de Jorn, bien qu'elle nécessiterait plus de changements de code. Comme vous le dites, c'est le plus portable. Merci beaucoup !! Lorsque je reçois un 15 représentant, je peux modifier votre réponse aussi.
Lorsqu'il est immobile à partir d'un INPURSTREAM ou d'un lecteur, l'analyseur ne connaît pas le système SystemID (URI / EMPLACEMENT) du document, il ne peut donc pas résoudre les chemins relatifs. Il semble que l'analyseur essaie de résoudre les références à l'aide du répertoire de travail actuel, qui fonctionne uniquement lors de l'exécution de la ligne IDE ou de commande. Afin de remplacer ce comportement et de vous résoudre, vous devez implémenter un Après quelques expériences, j'ai trouvé une façon standard de faire cela. Vous devez vous installer à partir d'un main.java strong> p> entitéresolver code>, comme l'a mentionné Blaise Dumdan.
saxsource code>, qui est à son tour construit à partir d'un
xmlreader code> et un
entréeSource code>. Dans cet exemple, la DTD est située à côté de la classe annotée et peut donc être trouvée dans la classe de classe. P>
Jorn - Ty pour votre réponse. Je suis d'abord essais la suggestion de Blaise car elle nécessite le moindre code change. Mais vous avez tous deux donné des réponses très utiles. Y a-t-il une façon de créer des crédits?
Mon approche fonctionnera, mais l'avantage de l'approche de Jorn est que vous restez la mise en œuvre de Jaxb agnostique qui est la solution la plus portable.
Voici une autre variation des réponses déjà donnée à l'aide de l'interface entityResolver code>. Ma situation résolvait des entités XML externes relatives d'un fichier XML à un autre dans une hiérarchie de dossiers. Le paramètre du constructeur ci-dessous est le dossier XML "Working", pas le répertoire de travail du processus.
public class FileEntityResolver implements EntityResolver {
private static final URI USER_DIR = SystemUtils.getUserDir().toURI();
private URI root;
public FileEntityResolver(File root) {
this.root = root.toURI();
}
@Override @SuppressWarnings("resource")
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
URI systemURI;
try {
systemURI = new URI(systemId);
} catch (URISyntaxException e) {
return null;
}
URI relative = USER_DIR.relativize(systemURI);
URI resolved = root.resolve(relative);
File f = new File(resolved);
FileReader fr = new FileReader(f);
// SAX will close the file reader for us
return new InputSource(fr);
}
}