Для чего вы используете логические переменные?Чтобы отслеживать вложение?
Недавно я реализовал это, используя перечисление для каждого элемента.Код работает, но это грубое приближение к нему: «1003 *
enum Element {
// special markers:
ROOT,
DONT_CARE,
// Element tag parents
RootElement( "root" ROOT),
AnElement( "anelement"), // DONT_CARE
AnotherElement( "anotherelement"),// DONT_CARE
AChild( "child", AnElement),
AnotherChild( "child", AnotherElement);
Element() {...}
Element(String tag, Element ... parents) {...}
}
class MySaxParser extends DefaultHandler {
Map<Pair<Element, String>, Element> elementMap = buildElementMap();
LinkedList<Element> nestingStack = new LinkedList<Element>();
public void startElement(String namespaceURI, String sName, String qName, Attributes attrs) {
Element parent = nestingStack.isEmpty() ? ROOT : nestingStack.lastElement();
Element element = elementMap.get(pair(parent, sName));
if (element == null)
element = elementMap.get(DONT_CARE, sName);
if (element == null)
throw new IllegalStateException("I did not expect <" + sName + "> in this context");
nestingStack.addLast(element);
switch (element) {
case RootElement: ... // Probably don't need cases for many elements at start unless we have attributes
case AnElement: ...
case AnotherElement: ...
case AChild: ...
case AnotherChild: ...
default: // Most cases here. Generally nothing to do on startElement
}
}
public void endElement(String namespaceURI, String sName, String qName) {
// Similar to startElement() but most switch cases do something with the data.
Element element = nestingStack.removeLast();
if (!element.tag.equals(sName)) throw IllegalStateException();
switch (element) {
...
}
}
// Construct the structure map from the parent information.
private Map<Pair<Element, String>, Element> buildElementMap() {
Map<Pair<Element, String>, Element> result = new LinkedHashMap<Pair<Element, String>, Element>();
for (Element element: Element.values()) {
if (element.tag == null) continue;
if (element.parents.length == 0)
result.put(pair(DONT_CARE, element.tag), element);
else for (Element parent: element.parents) {
result.put(pair(parent, element.tag), element);
}
}
return result;
}
// Convenience method to avoid the need for using "new Pair()" with verbose Type parameters
private <A,B> Pair<A,B> pair(A a, B b) {
return new Pair<A, B>(a, b);
}
// A simple Pair class, just for completeness. Better to use an existing implementation.
private static class Pair<A,B> {
final A a;
final B b;
Pair(A a, B b){ this.a = a; this.b = b;}
public boolean equals(Object o) {...};
public int hashCode() {...};
}
}
* 1006» Редактировать:
Позиция в структуре XML отслеживаетсястек элементов.Когда вызывается startElement, соответствующее Element
перечисление может быть определено с использованием 1) родительского элемента из стека отслеживания и 2) тега элемента, переданного в качестве параметра sName в качестве ключа для карты, сгенерированной из родительской информации, определенной как частьперечисления Element
Класс Pair
является просто держателем ключа из двух частей.
Этот подход позволяет одному и тому же элементу-тегу, который неоднократно встречается в разных частях структуры XML с различной семантикой, быть представленным различными Element
перечисления.Например:
<root>
<anelement>
<child>Data pertaining to child of anelement</child>
</anelement>
<anotherelement>
<child>Data pertaining to child of anotherelement</child>
</anotherelement>
</root>
Используя эту технику, нам не нужно использовать флаги для отслеживания контекста, чтобы мы знали, какой элемент <child>
обрабатывается.Контекст объявляется как часть определения перечисления Element
и уменьшает путаницу за счет исключения различных переменных состояния.