Я пытаюсь прочитать XML-файл, предоставленный для базы данных IAM, чтобы структурировать базу данных. Я использую Matlab для чтения этих файлов и использую xmlread.

Файлы xml имеют размер более 1500, и почти все они дают одну и ту же ошибку:

Java exception occurred:
java.io.FileNotFoundException: http://www.fki.inf.unibe.ch/iamdb/form-metadata.dtd

    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)

    at org.apache.xerces.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)

    at org.apache.xerces.impl.XMLEntityManager.startEntity(Unknown Source)

Вот один из xml-файлов, которые я пытаюсь прочитать: http://pastebin.com/TtQz4ZCV

Не найденная ссылка вверху ведет на страницу 404, поэтому ее больше не существует, и они забыли ее исправить.

Есть ли у меня единственный вариант вручную удалить эту строку из всех файлов xml? или есть легкое исправление, чтобы прочитать это?

1
StuckInPhDNoMore 24 Июн 2016 в 18:20

1 ответ

Лучший ответ

Вам необходимо отключить внешнюю загрузку DTD для парсера. Для этого вы можете создать собственный DocumentBuilder, отключить внешнее DTD loading и передайте это как второй вход в xmlread.

Из скрытой документации xmlread (отображается, если вы открываете файл с помощью edit xmlread):

% Advanced use:
%   Note that FILENAME can also be an InputSource, File, or InputStream object
%   DOMNODE = XMLREAD(FILENAME,...,P,...) where P is a DocumentBuilder object
%   DOMNODE = XMLREAD(FILENAME,...,'-validating',...) will create a validating
%             parser if one was not provided.
%   DOMNODE = XMLREAD(FILENAME,...,ER,...) where ER is an EntityResolver will
%             will set the EntityResolver before parsing
%   DOMNODE = XMLREAD(FILENAME,...,EH,...) where EH is an ErrorHandler will
%             will set the ErrorHandler before parsing
%   [DOMNODE,P] = XMLREAD(FILENAME,...) will return a parser suitable for passing
%             back to XMLREAD for future parses.
%   

В итоге это выглядит примерно так:

% Create the DocumentBuilder
builder = javax.xml.parsers.DocumentBuilderFactory.newInstance;

% Disable validation
builder.setFeature('http://apache.org/xml/features/nonvalidating/load-external-dtd', false);

% Read your file
xml = xmlread(filename, builder);

Помните, что это может потенциально привести к неправильному синтаксическому анализу вашего файла.

Обновить

Итак, посмотрим на это немного внимательнее: как только мы преодолеем ошибку проверки DTD, FEX xml2struct не будет правильно обрабатывать запись DOCTYPE в XML и пытается обработать ее так же, как обычный узел. Вы можете изменить источник xml2struct, чтобы обнаружить это внутренне:

if node.getNodeType == node.DOCUMENT_TYPE_NODE

Однако, вероятно, было бы проще просто удалить все DOCTYPE для всех ваших файлов XML. Следующий сценарий должен уметь это делать.

folder = 'directory/where/all/files/live';

files = dir(fullfile(folder, '*.xml'));

for k = 1:numel(files)
    filename = fullfile(folder, files(k).name);
    fid = fopen(filename, 'rt');
    content = fread(fid, '*char')';
    fclose(fid);

    newcontent = regexprep(content, '\n\s*?<!DOCTYPE.*?(?=\n)', '');

    fout = fopen(filename, 'wt');
    fwrite(fout, newcontent);
    fclose(fout);
end
2
Suever 24 Июн 2016 в 20:39
Спасибо, теперь это открывает файл. Но я получаю еще одну ошибку при получении данных от одного из дочерних узлов. Я использую getNodeData. Это дает ошибку Undefined function 'toCharArray' for input arguments of type 'double'.. Но когда я редактирую свой xml-файл и удаляю ссылку dtd в строке 3. И не использую построитель, я могу открыть файл и получить данные из xml-файла. Вы упомянули, что построитель может неправильно проанализировать мой файл. Это причина ошибки?
 – 
StuckInPhDNoMore
24 Июн 2016 в 19:30
1
Я разберусь с этим. Но пока что вы можете удалить эту строку из одного файла, загрузить ее и сохранить второй вывод P выше. Затем передайте это вместо builder, чтобы попытаться прочитать другой файл
 – 
Suever
24 Июн 2016 в 19:32
Спасибо за быстрый ответ. Теперь я снова получаю первоначальную ошибку исключения Java. Я прочитал отредактированный файл xml со вторым выходом p, а затем использовал p вместо builder в качестве второго аргумента при чтении неотредактированного файла xml.
 – 
StuckInPhDNoMore
24 Июн 2016 в 19:47
1
Можете ли вы дать ссылку на реальный код, который вы пытаетесь запустить?
 – 
Suever
24 Июн 2016 в 19:48
1
Оказывается, это ошибка в xml2struct. Я разместил код, чтобы просто удалить все эти записи <!DOCTYPE>
 – 
Suever
24 Июн 2016 в 20:40