Файл разбора, содержащий фрагменты XML в Java - PullRequest
2 голосов
/ 13 июля 2010

Я унаследовал файл лицензии «XML», в котором нет корневого элемента, а есть два фрагмента XML (<XmlCreated> и <Product>), поэтому при попытке проанализировать файл я (ожидаемо) получаю сообщение об ошибке, что плохо сформирован.

Мне нужно получить теги XmlCreated и Product.

Пример XML-файла:

<?xml version="1.0"?>

<XmlCreated>May 11 2009</XmlCreated>

<!-- License Key file Attributes -->
<Product image ="LicenseKeyFile">

 <!-- MyCompany -->
 <Manufacturer ID="7f">
  <SerialNumber>21072832521007</SerialNumber>
  <ChassisId>72060034465DE1C3</ChassisId>
  <RtspMaxUsers>500</RtspMaxUsers>
  <MaxChannels>8</MaxChannels>
 </Manufacturer>

</Product>

Вот текущий код, который я использую, чтобы попытаться загрузить XML. Это не работает, но я уже использовал его в качестве отправной точки для правильно сформированного XML.

public static void main(String[] args) {
    try {
        File file = new File("C:\\path\\LicenseFile.xml");
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(file);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

В строке db.parse(file) я получаю следующее исключение:

[Fatal Error] LicenseFile.xml:6:2: The markup in the document following the root element must be well-formed.
org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.
 at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
 at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
 at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
 at com.mycompany.licensesigning.LicenseSigner.main(LicenseSigner.java:20)

Как мне разобрать этот расстраивающий файл?

Ответы [ 5 ]

2 голосов
/ 13 июля 2010

Если вы знаете, что этот документ всегда будет плохо сформирован ... сделайте это так.Добавьте новый фиктивный тег <root> после <?xml...> и </root> после последних данных.

1 голос
/ 13 июля 2010

Вам нужно будет создать два отдельных объекта Document, разбив файл на более мелкие части и проанализировав эти части по отдельности (или, в качестве альтернативы, восстановив их в более крупный документ, добавив тег, который объединяет их оба).

Если вы можете положиться на структуру файла, должно быть легко прочитать файл в строку, а затем найти подстроки, такие как <Product и </Product>, а затем использовать эти маркеры для создания строки, в которую вы можете передать конструктор документов.

0 голосов
/ 13 июля 2010

Я в некоторой степени согласен с Джимом Гаррисоном, использую InputStream или StreamReader и упаковываю ввод в требуемые теги, это простой и легкий метод.Основная проблема, которую я могу предвидеть, состоит в том, что вам нужно будет выполнить несколько проверок на допустимое и недействительное форматирование (если вы хотите использовать метод для допустимых и недействительных данных), если форматирование недопустимо (из-за отсутствия тегов корневого уровня) оберните ввод тегами, если он допустим, не оборачивайте ввод.Если ввод недопустим по какой-либо другой причине, вы также можете изменить ввод для исправления проблем с форматированием.

Кроме того, вероятно, лучше хранить ipnut в коллекции строк (некоторого вида), а не всама строка, это будет означать, что у вас не будет столько ограничений на ваш размер ввода.Сделайте каждую строку одной строкой из файла.В итоге вы должны получить логичную и простую в использовании структуру, которая позволит в будущем исправлять другие проблемы с форматированием.

Самое сложное в этом - выяснить, что послужило причиной неправильного форматирования.В вашем случае просто проверьте теги корневого уровня, если теги существуют и правильно отформатированы, не переносите, если нет, переносите.

0 голосов
/ 13 июля 2010

Я бы, вероятно, создал бы SequenceInputStream, где вы сэндвич реального потока с двумя ByteArrayInputStreams, которые возвращают некоторый фиктивный корневой начальный тег и конечный тег.

Затем я бы использовал метод parse, который принимает потока не имя файла.

0 голосов
/ 13 июля 2010

Как насчет реализации простой оболочки вокруг InputStream, которая оборачивает входные данные из файла тегом корневого уровня и использует его в качестве входных данных для DocumentBuilder.parse()?

Если ожидаемый входной сигнал достаточно мал, чтобызагрузить в память, прочитать в строку, обернуть ее фиктивным начальным / конечным тегом и затем использовать:

DocumentBuilder.parse(new InputSource(new StringReader(string)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...