2015-02-28 4 views
0

Итак, я столкнулся с этой проблемой, когда мне нужно проанализировать XML-файл, чтобы портировать объекты домена. Звучит достаточно просто, однако элемент в файле XML может иметь неизвестное количество детей, поэтому объект домена может иметь переменную экземпляра для другого объекта класса, этот объект может иметь переменную для переменной экземпляра того же класса и так далее. Чтобы дать вам пример, это при условии, пример файла XML:SAX синтаксический анализ и отношения родителя/ребенка

<categories> 
    <category id="1"> 
     <name>XML</name> 
     <category id="2"> 
      <name>XPath</name> 
     </category> 
     <category id="3"> 
      <name>XML Schema</name> 
     </category> 
     <category id="4"> 
      <name>XSLT</name> 
     </category> 
     <category id="5"> 
      <name>XSL-FO</name> 
     </category> 
     <category id="6"> 
      <name>XQuery</name> 
     </category> 
    </category> 
    <category id="7"> 
     <name>Java</name> 
     <category id="100"> 
      <name>SDK</name> 
      <category id="8"> 
       <name>Collections</name> 
      </category> 
      <category id="9"> 
       <name>NIO</name> 
      </category> 
      <category id="10"> 
       <name>Concurrency</name> 
      </category> 
     </category> 
     <category id="1000"> 
      <name>EE</name> 
      <category id="11"> 
       <name>EJB</name> 
      </category> 
      <category id="12"> 
       <name>Web</name> 
      </category> 
      <category id="13"> 
       <name>Webservices</name> 
      </category> 
     </category> 
     <category id="0"> 
      <name>Examen boeken</name> 
     </category> 
    </category> 
</categories> 

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

На данный момент мне удалось получить все записи категории на карте, содержащей их идентификатор и имя.

код выглядит следующим образом:

public static void main(String[] args) throws SAXException, IOException, 
     ParserConfigurationException { 
    Bookshelf mijnBookshelf = new Bookshelf("boekenfestijn"); 
    Map<Integer, Category> categories = new HashMap<Integer, Category>(); 
    // TODO inlezen 
    try { 

     SAXParserFactory factory = SAXParserFactory.newInstance(); 
     SAXParser saxParser = factory.newSAXParser(); 

     DefaultHandler handler = new DefaultHandler() { 

      String reading = null; 

      boolean inCategory = false; 
      boolean inName = false; 

      int categoryId; 

      Category currentCategory; 


      public void startElement(String uri, String localName, 
        String qName, Attributes attributes) 
        throws SAXException { 

       if(qName.equalsIgnoreCase("CATEGORY") && attributes.getValue("id") != null){ 
        inCategory = true; 
        categoryId = Integer.parseInt(attributes.getValue("id")); 
        System.out.println("START HANDLING ID -> " + attributes.getValue("id")); 

       } 
       if(qName.equalsIgnoreCase("NAME")){ 
        inName = true; 
       } 


      } 

      public void endElement(String uri, String localName, 
        String qName) throws SAXException { 


       if(inCategory){ 
        inCategory = false; 
        System.out.println("CATEGORY ID : " + categoryId + " NAME : " + reading); 
        currentCategory = new Category(categoryId, reading); 
        currentCategory.setBookshelf(mijnBookshelf); 
        categories.put(categoryId, currentCategory); 
        System.out.println("END HANDLING"); 
       } 

       if(inName){ 
        inName = false; 
       } 



      } 













      public void characters(char ch[], int start, int length) 
        throws SAXException { 
       reading = new String(ch, start, length); 


      } 

     }; 

     saxParser.parse("bookshelf.xml", handler); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    for (Integer i : categories.keySet()) { 
     System.out.println("ID: " + categories.get(i).getId() + "->" 
       + categories.get(i).getName()); 
    } 

И для «категории» класса

public class Category { 

private Integer id; 
private String name; 
private Category parent; 
private List<Category> children = new ArrayList<Category>(); 
private Bookshelf bookshelf; 

public Category(){ 

} 

public Category(Integer id, String name) { 
    super(); 
    this.id = id; 
    this.name = name; 
} 

public Integer getId() { 
    return id; 
} 

public void setId(Integer id) { 
    this.id = id; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public Category getParent() { 
    return parent; 
} 

public void setParent(Category parent){ 
    this.parent = parent; 
} 

public List<Category> getChildren() { 
    return children; 
} 

public String toString() { 
    String s = bookshelf.getName() + "/"; 
    if (parent != null) { 
     s = parent.toString(); 
    } 
    s += name + "/"; 
    return s; 
} 

public Bookshelf getBookshelf() { 
    return bookshelf; 
} 

public void setBookshelf(Bookshelf bookshelf) { 
    this.bookshelf = bookshelf; 
} 

И это точка, в которой я застрять? как я могу перейти к определению родительских отношений с детьми? как бы я знал в какой-либо момент моего обработчика, какой элемент имеет какой элемент в качестве child/parent?

Любая помощь была бы принята с благодарностью!

TLDR: Как определить отношения родителя/ребенка при использовании парсера sax для заполнения объектов домена?

+1

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

+0

Я дам эту попытку, звучит логично. –

+0

Работал как шарм! –

ответ

2

В SAX вы не можете знать, какой элемент является родителем другого. Общим способом обработки этой информации является управление стеком LIFO (например, java.util.Stack). Вы нажимаете элемент по методу startElement() и выталкиваете его на endElement().

И, к сожалению, невозможно предсказать дочерние элементы до тех пор, пока вы не «встретите» их благодаря startElement().

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