Как сопоставить catalog.xml сущности с базой данных?
Я должен проверить некоторые файлы XML с файлами.xsd, которые перечислены в catalog.xml, но они находятся в базе данных. Поэтому мне нужен распознаватель, который будет сопоставлять systemId из catalog.xml с файлом.xsd, хранящимся в виде BLOB-объекта в базе данных. я нашел это XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier)
метод делает это, но я не могу найти, как синтаксический анализатор использует этот метод, поэтому я не уверен, как переопределить его, чтобы сделать это правильно. Я думал, что это возвращает XMLInputStram
который содержит файл.xsd в Stream, но это не так из-за "оставления разрешения сущности и открытия входного потока до вызывающей стороны", согласно документации XMLInputSource.
Поэтому мой вопрос - как сопоставить сущности из catalog.xml с файлами.xsd, хранящимися в базе данных?
Я действительно надеюсь, что я объяснил проблему ясно, но я знаю, что мой английский действительно плохой - так что не стесняйтесь спрашивать больше деталей или лучшего объяснения.
Привет, Рзыся
2 ответа
Хорошо, я нашел решение - как я думал, метод XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier)
shoud вернуть XMLInputSource с установленным моим собственным InputStream, содержащим конкретную xsd-схему. Моя версия этого переопределенного класса:
public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier)
throws XNIException, IOException {
String resolvedId = resolveIdentifier(resourceIdentifier);
if (resolvedId != null) {
XMLInputSource xmlis = new XMLInputSource(resourceIdentifier.getPublicId(),
resolvedId,
resourceIdentifier.getBaseSystemId());
try {
InputStream is = getXSDFromDb(resourceIdentifier.getLiteralSystemId());
xmlis.setByteStream(is);
} catch (SQLException ex) {
ex.printStackTrace();
}
return xmlis;
}
return null;
Вот решатель, который я написал для плагина maven-jaxb2-. Этот преобразователь разрешает системные идентификаторы для ресурсов в артефактах Maven. Это несколько похоже на вашу задачу.
- Ваша задача, в основном, реализовать
resolveEntity
метод. - Обычно целесообразно расширить существующий
CatalogResolver
, - Тогда вы можете переопределить
getResolvedEntity
метод. - Обычно вы сначала вызываете метод super для разрешения
systemId
/publicId
, - Затем вы пытаетесь сделать собственное разрешение.
systemId
обычно это URL-адрес расположения ресурса (или логический URI).publicId
часто это URI пространства имен.
Вот простой фрагмент кода от другого распознавателя, который разрешает classpath:com/acme/foo/schema.xsd
в пути к классам:
public static final String URI_SCHEME_CLASSPATH = "classpath";
@Override
public String getResolvedEntity(String publicId, String systemId) {
final String result = super.getResolvedEntity(publicId, systemId);
if (result == null) {
return null;
}
try {
final URI uri = new URI(result);
if (URI_SCHEME_CLASSPATH.equals(uri.getScheme())) {
final String schemeSpecificPart = uri.getSchemeSpecificPart();
final URL resource = Thread.currentThread()
.getContextClassLoader()
.getResource(schemeSpecificPart);
if (resource == null) {
return null;
} else {
return resource.toString();
}
} else {
return result;
}
} catch (URISyntaxException urisex) {
return result;
}
}
В вашем сценарии я бы сделал следующее:
- Определите схему URI как
database:schema:table:value:id:schema.xsd
, - Напишите средство распознавания каталога, способное разрешать такие URI.
- Определите файл каталога, который перезаписывает URI пространства имен или URL-адреса абсолютного расположения схемы для вашего
database:...
URIs.
В простой записи это будет что-то вроде:
REWRITE_SYSTEM "http://example.com/schemas" "database:schemas:content:schema_id:example/schemas"
- Таким образом, "базовый" преобразователь каталога сначала разрешит
http://example.com/schemas/schema.xsd
вdatabase:schemas:content:schema_id:example/schemas/schema.xsd
, - Тогда ваш код разрешается
database:schemas:content:schema_id:example/schemas/schema.xsd
в ресурс базы данных.