Инструменты пользователя

Инструменты сайта


java:morpher

Библиотека для склонения по падежам

Если вы имеете дело с базами данных, в которых хранится информация о персональных данных, рано или поздно встает вопрос о склонении по падежам. Самый простой способ - вводить фамилии, имена и отчества в требуемых падежах вручную, но можно ли как-то автоматизировать этот процесс? Оговорюсь сразу, что я не являюсь знатоком русского языка, не смотря на то, что всю свою жизнь прожил в России. Я о том, что написать алгоритм склонения самому для меня сложно. Проще использовать что-то готовое.

Сейчас на рынке можно найти библиотеки для склонения по падежам, но как-правило, все они коммерческие и мало что попадается под Linux. Во время очередных поисков решения проблемы, я набрел на сайт морфер.ру на котором есть как готовые решения в виде модулей и библиотек, так и бесплатный онлайн-сервис склонения. Этот бесплатный сервис я и решил использовать на потребу своей черной душе в этой статье. Итак, приступим.

Немного теории

Веб-сервис работает посредством простых GET-запросов (надеюсь, вы знаете, что такое GET). Чтобы что-то просклонять, надо выполнить запрос

http://morpher.ru/WebService.asmx/GetXml?s=тест

где «тест» - это слово или выражение, которое надо просклонять. Результатом работы сервиса будет XML-документ следующего содержания:

<?xml version="1.0" encoding="utf-8"?>
<xml xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://morpher.ru/">
  >теста</Р>
  >тесту</Д>
  >тест</В>
  >тестом</Т>
  >тесте</П>
  <множественное>
    >тесты</И>
    >тестов</Р>
    >тестам</Д>
    >тесты</В>
    >тестами</Т>
    >тестах</П>
  </множественное>
</xml>

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

Итак, мы получили XML-документ, в котором есть как полезное, так и лишнее. Как получить то, что нам нужно? Конечно же пропарсить XML-документ. В Java для этого есть несколько библиотек. Самые популярные из них - DOM и SAX. В этой статье будет использоваться DOM. В литературе упоминается, что DOM потребляет больше памяти и используется тогда, когда нужно не просто вытащить кусок текста из XML, а выполнить что-то большее. Вроде как, SAX нам больше подходит, исходя из книжных описаний, но поживем - увидим.

Пишем класс

Итак, руководствуясь вторым томом книги Кея С. Хорстманна и Гари Корнелла «Java 2. Библиотека профессионала», я принялся писать класс. Вот то, что у меня получилось:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package morpher;
 
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
 
/**
 *
 * @author leonid
 */
public class Morpher {
  private Document doc = null;
 
  public Morpher(String word) throws IOException, ParserConfigurationException, SAXException {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    doc = builder.parse("http://morpher.ru/WebService.asmx/GetXml?s="+word);
  }
 
 
  public String getRootElement() {
    String result = "";
    if (null != doc) {
      Element el = doc.getDocumentElement();
      result = el.getTagName();
    }
    return result;
  }
 
 
  public String getMorph(String p) {
    String result = "";
    if (null != doc) {
      Element root = doc.getDocumentElement();
      NodeList nodes = root.getChildNodes();
      for (int x = 0; x < nodes.getLength(); x++) {
        Node item = nodes.item(x);
        if (item instanceof Element) {
          Element el = ((Element)item);
          if (el.getTagName().equals(p)) {
            result = ((Text)el.getFirstChild()).getData().trim();
          }
        }
      }
    }
    return result;
  }
 
}

В классе объявлена private-переменная doc, которая хранит XML-документ. Далее, в классе имеются конструктор и пара методов. Конструктор создает экземпляр класса и принимает один параметр - слово или выражение, которое подлежит склонению. Это выражение подставляется в запрос на веб-сервис проекта morpher.ru, ответ которого и будет храниться в переменной doc. На случай, если что-то пойдет не так, класс порождает несколько исключений, которые должны перехватываться там, где будет использован этот класс.

Метод getRootElement() был создан по большей части для тестирования на начальном этапе. В принципе, он не нужен. Все, что он делает - это возвращает имя корневого элемента. В случае с морфером, это будет xml.

Метод getMorph(String p) - это то, ради чего все затевалось. Он возвращает результат склонения выражения по требуемому падежу. Падеж (точнее, его первую заглавную букву) надо передать методу в качестве параметра. В принципе, реализовать метод можно было и по-другому, но я пока остановился на этом варианте.

Проверяем работу класса

Для проверки работоспособности, я написал примитивный класс Main:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package morpher;
 
/**
 *
 * @author leonid
 */
public class Main {
 
  /**
   * @param args the command line arguments
   */
  public static void main(String[] args) {
 
    try {
      System.out.println("Executing...");
      Morpher morph = new Morpher("Умножение");
      System.out.println("Root element is "+morph.getRootElement());
      System.out.println("Родительный падеж: "+morph.getMorph("Р"));
      System.out.println("Дательный падеж: "+morph.getMorph("Д"));
      System.out.println("Винительный падеж: "+morph.getMorph("В"));
      System.out.println("Творительный падеж: "+morph.getMorph("Т"));
      System.out.println("Предложный падеж: "+morph.getMorph("П"));
    } catch (Exception e) {
      System.out.println("Exception occured: "+e.getMessage());
    }
  }
}

В примере создается экземпляр класса Morpher, методы которого вызываются в последствии для отображения на экране выражения в различных падежах.

Заключение

Полученный класс (Morpher) будет использован для автоматизации склонения имен в моих дальнейших проектах. Единственный существенный недостаток - необходимость подключения к интернету. Теоретически, чтобы просклонять все имена, фамилии и отчества базы данных нашего учебного заведения, необходимо:

  • уметь работать с JDBC,
  • знать о существовании запроса SELECT DISTINCT…
  • подключение к интернету на час, два (максимум - ночь)

На этом, пока все. Пойду склонять все, что попадется под руку. Спасибо за внимание.

В начало раздела

java/morpher.txt · Последние изменения: 2014/08/12 08:23 — gooamoko

Инструменты страницы