java
  • xml
  • performance
  • xml-parsing
  • sax
  • 2013-09-04 2 views 1 likes 
    1

    У меня есть серия XML, содержащая почтовые индексы с соответствующей их широтой и долготой, например;Эффективная обработка SAX

    <?xml version="1.0"?> 
    <postcodes> 
        <entry postcode='AB1 0AA' latitude='7.101478' longitude='2.242852' /> 
        <entry postcode='AB1 0AB' latitude='7.201458' longitude='2.122952' /> 
    </postcodes> 
    

    В XMLs разделены на почтовые коды, начинающиеся с определенной буквы, поэтому есть один XML для каждой буквы в алфавите. Между ними у них есть каждый почтовый код в Великобритании, что означает, что самый большой из этих файлов XML содержит 300 000 entry элементов.

    Я просматриваю список объектов Entity, чтобы поместить их почтовые коды через SAX, чтобы получить значения longitude и latitude против каждого почтового кода. Итак, если у меня есть объекты объектов 2000, я получаю обработчик SAX для запуска 2000 раз, чтобы получить эти значения. Код для цикла ниже;

    em = emf.createEntityManager(); 
    
        for (Integer id : siteID){ 
          site = em.find(SiteTable.class, id); 
          if(site != null && site.getPostcode() != null && !site.getPostcode().equals("")){ 
           XMLPositionRetriever.runXMLQuery(site.getPostcode()); 
          } 
          else{ 
           System.out.println("The site and/or postcode against this Instruction does not exist."); 
          } 
        } 
    em.close(); 
    

    site.getPostcode() становится postcodeToFind в обработчике. Код для единственного метода обработчика SAX, который используется ниже;

    @Override 
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 
        if (postcodeToFind.equals(attributes.getValue("postcode"))){ 
         System.out.println("The postcode '"+postcodeToFind+"', has a latitude of "+attributes.getValue("latitude")+" and a longitude of "+attributes.getValue("longitude")); 
         throw new SAXException(); 
        }  
    } 
    

    В настоящее время это отнимает много времени (это занимает менее 4 минут на 2000 запросов), но мне нужно время загрузки, чтобы быть быстрым. До 30 секунд предпочтительно. До сих пор мне удалось сократить время загрузки намного ниже половины;

    • Сокращение количества обработчиков, которые должен выполняться обработчиком, только до необходимого количества раз (путем уменьшения количества объектов, подлежащих проверке).
    • Создание метода startElement() генерирует исключение, как только нужные мне данные были найдены, так что он не будет продолжать поиск без необходимости.
    • Ломать файлы XML в файлы меньшего размера (по одному на каждую букву алфавита), чтобы у обработчика было меньше элементов для проверки на файл.

    Вопрос: Есть ли у кого-нибудь другие предложения по более эффективной обработке SAX?

    +0

    Если память не является ключевым требованием здесь, дерево доминирования этого файла (возможно, используя современные методы, такие как JAXB или XStream), может ускорить это чтение файла один раз, а затем доступ ко всему материалу в памяти. Это может улучшить производительность существенным фактором (за счет увеличения потребления памяти). – Matthias

    +0

    Вы можете использовать Apache Tika и использовать регулярное выражение для получения значений –

    +0

    Использовать базу данных вместо XML-файлов? –

    ответ

    2

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

    import java.util.HashMap; 
    import java.util.List; 
    import java.util.Map; 
    
    import org.xml.sax.Attributes; 
    import org.xml.sax.SAXException; 
    import org.xml.sax.helpers.DefaultHandler; 
    
    public class SAXDemo extends DefaultHandler { 
    
        private Map<String, Location> postalCodeMap; 
    
        static class Location { 
        String latitude; 
    
        String longitude; 
        } 
    
        public SAXDemo(List<String> postalCodes) { 
        this.postalCodeMap = new HashMap<String, SAXDemo.Location>(); 
        for (String postalCodeToLookFor : postalCodes) { 
         this.postalCodeMap.put(postalCodeToLookFor, new Location()); 
        } 
        } 
    
        @Override 
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 
        String postCodeOfElem = attributes.getValue("postcode"); 
        if (postCodeOfElem != null && this.postalCodeMap.containsKey(postCodeOfElem)) { 
         Location loc = this.postalCodeMap.get(postCodeOfElem); 
         loc.latitude = attributes.getValue("latitude"); 
         loc.longitude = attributes.getValue("longitude"); 
        } 
        } 
    
        public Location getLocationForPostalCode(String postalCode) { 
        return this.postalCodeMap.get(postalCode); 
        } 
    
        public Map<String, Location> getAllFoundGeoLocations() { 
        return this.postalCodeMap; 
        } 
    } 
    

    Здесь вы передаете список строк в конструктор обработчика, а затем пусть обработчик разбора документа со всеми вашими данными XML. После того, как синтаксический анализ завершен, все найденные географические местоположения можно найти в postalCodeMap

    +0

    Это кровавый гений. Я посмотрю, смогу ли я заставить его работать. –

    +0

    Мне потребовалось немало возиться с моим проектом, чтобы заставить его работать, и мне пришлось скомпилировать все XML-почтовые индексы в один большой файл с 2 с половиной миллионов элементов. Потребовалось всего одну минуту, чтобы запустить весь проект раньше, большинство из которых было занято синтаксическим анализом SAX. Теперь весь проект работает через 10 секунд. –

    +0

    Эй, рад, что это помогло! – Matthias

    Смежные вопросы