Подтвердить что ты не робот

SGML-парсер в Java?

Я ищу парсер в Java, который может анализировать документ, отформатированный в SGML.

Для дублирующих мониторов: Я знаю два других потока, которые обсуждают эту тему: Разбор строки Java с SGML Преобразование Java SGML в XML? Но ни одна из них не имеет разрешения, следовательно, новая тема.

Для людей, которые смешивают XML с SGML: Пожалуйста, прочтите следующее: http://www.w3.org/TR/NOTE-sgml-xml-971215#null (короче говоря, есть достаточно тонких различий, чтобы хотя бы сделать его непригодным для использования в ванильной форме)

Для людей, которые любят просить плакаты в Google, он: Я уже сделал это и самый близкий, с которым я мог придумать, был широко популярным SAXParser: http://download.oracle.com/javase/1.4.2/docs/api/javax/xml/parsers/SAXParser.html Но это, конечно, предназначено для анализа XML. Я смотрю вокруг, чтобы увидеть, внедрил ли кто-нибудь модификацию SAX Parser для размещения SGML.

Наконец, я не могу использовать SX, поскольку я ищу решение Java.

Спасибо!:)

4b9b3361

Ответ 1

У меня есть несколько подходов к этой проблеме

Первое - это то, что вы сделали - проверьте, достаточно ли документа sgml достаточно для XML, чтобы стандартный анализатор SAX работал.

Во-вторых, делать то же самое с анализаторами HTML. Трюк здесь заключается в том, чтобы найти тот, который не игнорирует не-HTML-элементы.

Я нашел несколько синтаксисов Java SGML, больше в acedemia, при поиске "sgml parser Java". Я не знаю, насколько хорошо они работают.

Последний шаг - принять стандартный (не Java) синтаксический анализатор SGML и преобразовать документы во что-то, что вы можете прочитать на Java.

Похоже, вы смогли работать с первым шагом.

Ответ 2

В настоящее время нет api для синтаксического анализа SGML с использованием Java. Там также нет каких-либо api или библиотеки для преобразования SGML в XML и последующего анализа его с помощью Java. Поскольку статус SGML вытесняется XML для всех проектов, над которыми я работал до сих пор, я не думаю, что в этой области будет любая работа, но это только предположение.

Здесь - это код с открытым кодом из университета, который это делает, однако я не пробовал, и вам придется искать найти другие зависимые классы. Я считаю, что единственное жизнеспособное решение на Java потребует регулярных выражений.

Кроме того, здесь приведена ссылка для общедоступного программного обеспечения SGML/XML.

Ответ 3

Java SE включает парсер HTML в пакете javax.swing.text.html.parser. В своей документации он утверждает, что он является общим синтаксическим анализатором SGML, но затем встречает в документации, что вы должны использовать его только с предоставленным HTML DTD классом.

Если вы поместили его в режим снисхождения, и ваши документы SGML не имеют много подразумеваемых конечных тегов, вы можете получить разумные результаты.

Читайте о парсере в своем JavaDoc, здесь: http://docs.oracle.com/javase/6/docs/api/javax/swing/text/html/parser/DocumentParser.html

Создайте такой экземпляр:

new DocumentParser(DTD.getDTD("html32"))

Или вы можете игнорировать предупреждения против использования пользовательского DTD с DocumentParser и создать подкласс DTD, который соответствует правилам вашего собственного формата SGML.

Это явно не промышленный синтаксический анализатор SGML, но он должен стать хорошей отправной точкой для одноразовой миграции данных. Я нашел это полезным в предыдущих проектах для разбора HTML.

Ответ 4

Я использую OpenSP через JNI, поскольку, похоже, нет чистого синтаксического анализа Java SGML. Я написал экспериментальную SAX-подобную оболочку, доступную в http://sourceforge.net/projects/sasgml (конечно, у нее есть все недостатки JNI... но этого было достаточно для моих требований).

Другой подход заключается в преобразовании документа в XML с помощью sx из Open SP, а затем запустить традиционный синтаксический анализатор SAX.

Ответ 6

Хотя это очень старый пост, и я не утверждаю, что ответ, который я предоставляю, идеален, но он служил моей цели. Поэтому я сохраняю этот код, который я написал, используя стек, чтобы получить данные в пути, в моем случае. Я надеюсь, что это может быть полезно для других.

try (BufferedReader br = new BufferedReader(new FileReader(new File(
                fileName)))) {
            while ((line = br.readLine()) != null) {
                line = line.trim();
                int startOfTag = line.indexOf("<");
                int endOfTag = line.indexOf(">");
                String currentTag = "";

                if (startOfTag > -1 && endOfTag > -1) {
                    if (countStart)
                        headerTagsCounter++;
                    currentTag = line.substring(startOfTag + 1, endOfTag);
                    String currentData = line.substring(endOfTag + 1,
                            line.length());
                    if (i == 1) {
                        tagStack.push(currentTag);
                        i++;
                    }
                    if (currentData.isEmpty() || currentData == "") {//If there is no data, its a parent tag...
                        if (!currentTag.contains("/")) {// if its an opening tag...
                            switch (currentTag) {// these tags are useless in my case, so just skipping these tags.
                            case "CORRECTION":
                            case "PAPER":
                            case "PRIVATE-TO-PUBLIC":
                            case "DELETION":
                            case "CONFIRMING-COPY":
                            case "CAPTION":
                            case "STUB":
                            case "COLUMN":
                            case "TABLE-FOOTNOTES-SECTION":
                            case "FOOTNOTES":
                            case "PAGE":
                                break;
                            default: {
                                countStart = false;
                                int tagCounterNumber = 0;
                                String historyTagToRemove = "";
                                for (String historyTag : historyStack) {
                                    String tagCounter = "";
                                    if (historyTag.contains(currentTag)) {//if it  a repeating tag..Append the counter  and update the same  in history tag..
                                        historyTagToRemove = historyTag;
                                        if (historyTag
                                                .equalsIgnoreCase(currentTag)) {
                                            tagCounterNumber = 1;
                                        } else if (historyTag.length() > currentTag
                                                .length()) {
                                            tagCounter = historyTag
                                                    .substring(currentTag
                                                            .length());
                                            if (tagCounter != null
                                                    && !tagCounter.isEmpty()) {
                                                tagCounterNumber = Integer
                                                        .parseInt(tagCounter) + 1;
                                            }
                                        }
                                    }
                                }
                                if (tagCounterNumber > 0)
                                    currentTag += tagCounterNumber;
                                if (historyTagToRemove != null
                                        && !historyTagToRemove.isEmpty()) {
                                    historyStack.remove(historyTagToRemove);
                                    historyStack.push(currentTag);
                                }
                                tagStack.push(currentTag);
                                break;
                            }
                            }
                        } else// if its end of a tag... Match the current tag with top of stack and if its a match, pop  it out
                        {
                            currentTag = currentTag.substring(1);
                            String tagRemoved = "";
                            String topStackTag = tagStack.lastElement();
                            if (topStackTag.contains(currentTag)) {
                                tagRemoved = tagStack.pop();
                                historyStack.push(tagRemoved);
                            }
                            if (tagStack.size() < 2)
                                cik = "";
                            if (tagStack.size() == 2 && cik != null
                                    && !cik.isEmpty())
                                for (int j = headerTagsCounter - 1; j < tagList.size(); j++) {
                                    String item = tagList.get(j);
                                    if (!item.contains("@@")) {
                                        item += "@@" + cik;
                                        tagList.remove(j);
                                        tagList.add(j, item);
                                    }
                                }
                        }
                    } else {// if current tag has some data...
                        currentData = currentData.trim();
                        String stackValue = "";
                        for (String tag : tagStack) {
                            if (stackValue != null && !stackValue.isEmpty()
                                    && stackValue != "")
                                stackValue = stackValue + "||" + tag;
                            else
                                stackValue = tag;
                        }
                        switch (currentTag) {
                        case "ACCESSION-NUMBER":
                            accessionNumber = currentData;
                            break;
                        case "FILING-DATE":
                            dateFiled = currentData;
                            break;
                        case "TYPE":
                            formType = currentData;
                            break;
                        case "CIK":
                            cik = currentData;
                            break;
                        }
                        tagList.add(stackValue + "$$" + currentTag + "::"+ currentData);
                    }
                }
            }
// Now all your data is available with in tagList, stack is separated by ||,  key is separated by $$ and value is separated by ::
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
        }

    }

Выход:

Источник файла: http://10k-staging.s3.amazonaws.com/edgar0105/2016/12/20/935015/000119312516799070/0001193125-16-799070.hdr.sgml

Вывод кода:

SEC-HEADER$$SEC-HEADER::0001193125-16-799070.hdr.sgml : 20161220
SEC-HEADER$$ACCEPTANCE-DATETIME::20161220172458
SEC-HEADER$$ACCESSION-NUMBER::0001193125-16-799070
SEC-HEADER$$TYPE::485APOS
SEC-HEADER$$PUBLIC-DOCUMENT-COUNT::9
SEC-HEADER$$FILING-DATE::20161220
SEC-HEADER$$DATE-OF-FILING-DATE-CHANGE::20161220
SEC-HEADER||FILER||COMPANY-DATA$$CONFORMED-NAME::ARTISAN PARTNERS FUNDS [email protected]@0000935015
SEC-HEADER||FILER||COMPANY-DATA$$CIK::[email protected]@0000935015
SEC-HEADER||FILER||COMPANY-DATA$$IRS-NUMBER::[email protected]@0000935015
SEC-HEADER||FILER||COMPANY-DATA$$STATE-OF-INCORPORATION::[email protected]@0000935015
SEC-HEADER||FILER||COMPANY-DATA$$FISCAL-YEAR-END::[email protected]@0000935015
SEC-HEADER||FILER||FILING-VALUES$$FORM-TYPE::[email protected]@0000935015
SEC-HEADER||FILER||FILING-VALUES$$ACT::[email protected]@0000935015
SEC-HEADER||FILER||FILING-VALUES$$FILE-NUMBER::[email protected]@0000935015
SEC-HEADER||FILER||FILING-VALUES$$FILM-NUMBER::[email protected]@0000935015
SEC-HEADER||FILER||BUSINESS-ADDRESS$$STREET1::875 EAST WISCONSIN AVE STE [email protected]@0000935015
SEC-HEADER||FILER||BUSINESS-ADDRESS$$CITY::[email protected]@0000935015
SEC-HEADER||FILER||BUSINESS-ADDRESS$$STATE::[email protected]@0000935015
SEC-HEADER||FILER||BUSINESS-ADDRESS$$ZIP::[email protected]@0000935015
SEC-HEADER||FILER||BUSINESS-ADDRESS$$PHONE::[email protected]@0000935015
SEC-HEADER||FILER||MAIL-ADDRESS$$STREET1::875 EAST WISCONSIN AVE STE [email protected]@0000935015
SEC-HEADER||FILER||MAIL-ADDRESS$$CITY::[email protected]@0000935015
SEC-HEADER||FILER||MAIL-ADDRESS$$STATE::[email protected]@0000935015
SEC-HEADER||FILER||MAIL-ADDRESS$$ZIP::[email protected]@0000935015
SEC-HEADER||FILER||FORMER-COMPANY$$FORMER-CONFORMED-NAME::ARTISAN FUNDS [email protected]@0000935015
SEC-HEADER||FILER||FORMER-COMPANY$$DATE-CHANGED::[email protected]@0000935015
SEC-HEADER||FILER||FORMER-COMPANY1$$FORMER-CONFORMED-NAME::ZIEGLER FUNDS [email protected]@0000935015
SEC-HEADER||FILER||FORMER-COMPANY1$$DATE-CHANGED::[email protected]@0000935015
SEC-HEADER||FILER1||COMPANY-DATA1$$CONFORMED-NAME::ARTISAN PARTNERS FUNDS [email protected]@0000935015
SEC-HEADER||FILER1||COMPANY-DATA1$$CIK::[email protected]@0000935015
SEC-HEADER||FILER1||COMPANY-DATA1$$IRS-NUMBER::[email protected]@0000935015
SEC-HEADER||FILER1||COMPANY-DATA1$$STATE-OF-INCORPORATION::[email protected]@0000935015
SEC-HEADER||FILER1||COMPANY-DATA1$$FISCAL-YEAR-END::[email protected]@0000935015
SEC-HEADER||FILER1||FILING-VALUES1$$FORM-TYPE::[email protected]@0000935015
SEC-HEADER||FILER1||FILING-VALUES1$$ACT::[email protected]@0000935015
SEC-HEADER||FILER1||FILING-VALUES1$$FILE-NUMBER::[email protected]@0000935015
SEC-HEADER||FILER1||FILING-VALUES1$$FILM-NUMBER::[email protected]@0000935015
SEC-HEADER||FILER1||BUSINESS-ADDRESS1$$STREET1::875 EAST WISCONSIN AVE STE [email protected]@0000935015
SEC-HEADER||FILER1||BUSINESS-ADDRESS1$$CITY::[email protected]@0000935015
SEC-HEADER||FILER1||BUSINESS-ADDRESS1$$STATE::[email protected]@0000935015
SEC-HEADER||FILER1||BUSINESS-ADDRESS1$$ZIP::[email protected]@0000935015
SEC-HEADER||FILER1||BUSINESS-ADDRESS1$$PHONE::[email protected]@0000935015
SEC-HEADER||FILER1||MAIL-ADDRESS1$$STREET1::875 EAST WISCONSIN AVE STE [email protected]@0000935015
SEC-HEADER||FILER1||MAIL-ADDRESS1$$CITY::[email protected]@0000935015
SEC-HEADER||FILER1||MAIL-ADDRESS1$$STATE::[email protected]@0000935015
SEC-HEADER||FILER1||MAIL-ADDRESS1$$ZIP::[email protected]@0000935015
SEC-HEADER||FILER1||FORMER-COMPANY2$$FORMER-CONFORMED-NAME::ARTISAN FUNDS [email protected]@0000935015
SEC-HEADER||FILER1||FORMER-COMPANY2$$DATE-CHANGED::[email protected]@0000935015
SEC-HEADER||FILER1||FORMER-COMPANY3$$FORMER-CONFORMED-NAME::ZIEGLER FUNDS [email protected]@0000935015
SEC-HEADER||FILER1||FORMER-COMPANY3$$DATE-CHANGED::[email protected]@0000935015
SEC-HEADER||SERIES-AND-CLASSES-CONTRACTS-DATA||NEW-SERIES-AND-CLASSES-CONTRACTS$$OWNER-CIK::0000935015
SEC-HEADER||SERIES-AND-CLASSES-CONTRACTS-DATA||NEW-SERIES-AND-CLASSES-CONTRACTS||NEW-SERIES$$SERIES-ID::S000056665
SEC-HEADER||SERIES-AND-CLASSES-CONTRACTS-DATA||NEW-SERIES-AND-CLASSES-CONTRACTS||NEW-SERIES$$SERIES-NAME::Artisan Thematic Fund
SEC-HEADER||SERIES-AND-CLASSES-CONTRACTS-DATA||NEW-SERIES-AND-CLASSES-CONTRACTS||NEW-SERIES||CLASS-CONTRACT$$CLASS-CONTRACT-ID::C000179292
SEC-HEADER||SERIES-AND-CLASSES-CONTRACTS-DATA||NEW-SERIES-AND-CLASSES-CONTRACTS||NEW-SERIES||CLASS-CONTRACT$$CLASS-CONTRACT-NAME::Investor Shares