2011-02-01 2 views
19

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

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

Для людей, которые путают 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.

Спасибо! :)

+1

Люди по-прежнему использовать SGML? Я искренне любопытен - что он использовал в вашем случае? – skaffman

+0

У меня около 2500 документов, отформатированных в SGML. Мне нужно использовать данные для некоторого статистического анализа. Я объединяя краткую программу, чтобы определить распределение тегов, я просмотрел несколько из них, и они, похоже, используют только несколько тегов. В этом случае я мог бы легко использовать SAXParser. – user183037

+0

У меня есть десятки тысяч файлов SGML, и все это делается все время. SGML по-прежнему довольно широко используется в издательской индустрии, но неправда! – Woody

ответ

4

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

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

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

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

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

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

+1

Я не нашел ресурсов для синтаксического анализа Java SGML вообще - было бы здорово, если бы вы могли опубликовать ссылку, если найдете ее снова - спасибо! – user183037

+0

На самом деле, когда я снова посмотрел, я тоже ничего не нашел. –

+0

:) Это хорошо - спасибо за попытку! – user183037

1

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

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

Также имеется link для общего программного обеспечения SGML/XML.

1

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.

1

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

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

0

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

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's 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