Обновлено: этот код в порядке. Я обнаружил где-то логическую ошибку, которой нет в моем псевдокоде. Я обвинял это в том, что у меня не было опыта работы с Java.
В псевдокод ниже я пытаюсь проанализировать показанный XML. Может быть, это глупый пример, но мой код был слишком большим / конкретным, чтобы кто-либо мог получить реальную пользу от его просмотра и изучения опубликованных ответов. Так что это более занимательно, и, надеюсь, другие смогут извлечь уроки из ответа так же, как и я.
Я новичок в Java, но опытный программист на C++, что заставляет меня думать, что моя проблема заключается в моем понимании языка Java.
Проблема: когда парсер завершает работу, мой вектор заполнен неинициализированными коровами. Я создаю вектор коров с емкостью по умолчанию (что не должно влиять на его "размер", если это что-то вроде вектора C++ STL). Когда я распечатываю содержимое вектора коровы после синтаксического анализа, он дает правильный размер вектора, но все значения, похоже, никогда не были установлены.
Информация: я успешно проделал это с другими парсерами, у которых нет Vector поля, но в этом случае я бы хотел использовать Vector для накопления свойств Cow.
MoreInfo: Я не могу использовать дженерики (Vector <Cow>), поэтому, пожалуйста, не указывайте мне на них. :)
Заранее спасибо.
<pluralcow>
<cow>
<color>black</color>
<age>1</age>
</cow>
<cow>
<color>brown</color>
<age>2</age>
</cow>
<cow>
<color>blue</color>
<age>3</age>
</cow>
</pluralcow>
public class Handler extends DefaultHandler{
// vector to store all the cow knowledge
private Vector m_CowVec;
// temp variable to store cow knowledge until
// we're ready to add it to the vector
private Cow m_WorkingCow;
// flags to indicate when to look at char data
private boolean m_bColor;
private boolean m_bAge;
public void startElement(...tag...)
{
if (tag == pluralcow){ // rule: there is only 1 pluralcow tag in the doc
// I happen to magically know how many cows there are here.
m_CowVec = new Vector(numcows);
}else if (tag == cow ){ // rule: multiple cow tags exist
m_WorkingCow = new Cow();
}else if (tag == color){ // rule: single color within cow
m_bColor = true;
}else if (tag == age){ // rule: single age within cow
m_bAge = true;
}
}
public void characters(...chars...)
{
if (m_bColor){
m_WorkingCow.setColor(chars);
}else if (m_bAge){
m_WorkingCow.setAge(chars);
}
}
public void endElement(...tag...)
{
if (tag == pluralcow){
// that's all the cows
}else if (tag == cow ){
m_CowVec.addElement(m_WorkingCow);
}else if (tag == color){
m_bColor = false;
}else if (tag == age){
m_bAge = false;
}
}
}




Код мне нравится. Я говорю устанавливать точки останова в начале каждой функции и смотреть ее в отладчике или добавлять операторы печати. Моя интуиция подсказывает мне, что либо characters() не вызывается, либо setColor() и setAge() работают некорректно, но это только предположение.
Должен сказать, что я не большой поклонник этого дизайна. Однако вы уверены, что ваших персонажей когда-нибудь называют? (возможно, поможет несколько system.out). Если он никогда не вызывается, вы получите неинициализированную корову.
Кроме того, я бы не стал пытаться реализовать подобный XML-анализатор, поскольку вам нужно быть более устойчивым к проблемам проверки.
Вы можете использовать SAX или DOM4J или, что еще лучше, использовать дайджест Apache.
Кроме того, это переопределение org.xml.sax.helpers.DefaultHandler
Он выглядел как стандартный синтаксический анализатор, но я не был уверен, был ли это реальный класс или это был отдельный перевод из синтаксического анализатора C++ SAX ... Я все еще думаю, что вам нужно что-то, что может обрабатывать беспорядочный XML, если вы не уверены, что это подтверждено. Попробуйте посмотреть на дигестор apache ...
Кроме того, если у меня есть схема, я буду использовать JaxB или другой генератор кода, чтобы ускорить разработку кода интерфейса XML. Генераторы кода скрывают большую часть сложности работы непосредственно с SAX или DOM4J.
Когда вы говорите, что коровы не инициализированы, инициализируются ли свойства String нулевым значением? Или пустые строки?
Я знаю, что вы упомянули, что это псевдокод, но я просто хотел указать на несколько потенциальных проблем:
public void startElement(...tag...)
{
if (tag == pluralcow){ // rule: there is only 1 pluralcow tag in the doc
// I happen to magically know how many cows there are here.
m_CowVec = new Vector(numcows);
}else if (tag == cow ){ // rule: multiple cow tags exist
m_WorkingCow = new Cow();
}else if (tag == color){ // rule: single color within cow
m_bColor = true;
}else if (tag == age){ // rule: single age within cow
m_bAge = true;
}
}
Вам действительно стоит использовать здесь tag.equals (...) вместо tag == ...
public void characters(...chars...)
{
if (m_bColor){
m_WorkingCow.setColor(chars);
}else if (m_bAge){
m_WorkingCow.setAge(chars);
}
}
Я предполагаю, что вы знаете об этом, но на самом деле эти методы вызываются с символьным буфером с начальным и конечным индексами.
Также обратите внимание, что символы (...) могут вызываться несколько раз для одного текстового блока, возвращая небольшие фрагменты при каждом вызове: http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/ContentHandler.html#characters(char[****************************************************
"...SAX parsers may return all contiguous character data in a single chunk, or they may split it into several chunks..."
Я сомневаюсь, что вы столкнетесь с этой проблемой в приведенном вами простом примере, но вы также упомянули, что это упрощенная версия более сложной проблемы. Если в вашей исходной задаче ваш XML состоит из больших текстовых блоков, это следует учитывать.
Наконец, как уже упоминалось другими, если вы могли бы, было бы неплохо рассмотреть библиотеку маршалинга XML (например, JAXB, Castor, JIBX, XMLBeans, XStream, чтобы назвать несколько).
Отличный ответ! 1) Буфер символов: да, я упрощал псевдокод. 2) String.equals (): да, тоже упрощение. 3) символы () вызываются несколько раз: отличное примечание! Я должен быть уверен, что займусь этим делом. 4) Еще не нашел библиотеки маршалинга, которая работает на Blackberry JDE 4 (J2ME).
Ах, я не знал, что вы программируете для J2ME. Тогда это немного отличается, и, вероятно, вам будет полезно избежать этого дополнительного уровня абстракции и связанных с этим накладных расходов на обработку.
У вас есть ссылки на синтаксический анализатор SAX в Java? Я пишу для Blackberry, так что маленькие и быстрые - главные приоритеты.