我必须使用SAX解析器解析JAVA中的XML结构。
问题是结构是递归的,具有未指定的递归计数。这仍然不是什么大问题,最重要的是我无法利用XML命名空间功能,并且每个递归级别的标签都是相同的。
以下是结构示例。
<?xml version="1.0" encoding="UTF-8"?>
<RootTag>
<!-- LOADS OF OTHER TAGS -->
<Tags attribute="value">
<Tag attribute="value">
<SomeOtherTag></SomeOtherTag>
<Tags attribute="value">
<Tag attribute="value">
<SomeOtherTag></SomeOtherTag>
<Tags attribute="value">
<!-- MORE OF THE SAME STRUCTURE -->
</Tags>
</Tag>
</Tags>
</Tag>
</Tags>
<!-- LOADS OF OTHER TAGS -->
</RootTag>
正如您所看到的那样,有一个递归,更好的是一个未定义的递归数。现在我的问题是如何为每次递归提取所有数据,并将其保存在HashMap
中。
我可以为ContentHandler
的出现定义一个Tags
,并让它在HashMap
中提取内容并将其放回 master {{ 1}}在主要内容处理程序中定义,但我不确定要做到这一点。
如何在不使用命名空间的情况下提取和保存递归XML结构的内容?
答案 0 :(得分:3)
结帐this set of Javaworld articles on using SAX。它演示了使用SAX解析递归XML结构的简单方法。它创建一个状态机,为每个元素显示它可以包含哪些元素。当你的contentHandler遍历xml时,它会保持一个堆栈,显示它当前所在的元素。
答案 1 :(得分:0)
如果要通过SAX递归解析XML,则必须使用Stack并检查XML结构中的深度。对于我这种格式的XML结构(最大深度为3):
<Response action='categories'>
<Categories>
<Category name='{name}' id='{id}' numSubcategories='{num}'>
<Category name='{name}' id='{id}' numSubcategories='{num}'>
<Category name='{name}' id='{id}' numSubcategories='0'/>
...
</Category>
...
</Category>
...
</Categories>
</Response>
我使用了这个Java伪代码,它在我的Android应用程序中运行得非常好(已知深度)。如果你不知道递归的数量并且不知道深度,你可以只编辑我的代码并代替3个ArrayList对象(和3个Category对象),你可以使用一个动态集合(用于示例ArrayList<ArrayList<Category>>
)并将ArrayList<Category>
放入ArrayList<ArrayList<Category>>
使用索引,该索引显示getDepth()
方法。
public class CategoriesResponse extends Response
{
private Stack<String> mTagStack = new Stack<String>();
private ArrayList<Category> mCategories1;
private ArrayList<Category> mCategories2;
private ArrayList<Category> mCategories3;
Category mCategory1;
Category mCategory2;
Category mCategory3;
private int mCurrentDepth = 0;
public ArrayList<Category> getCategories()
{
return mCategories1;
}
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
super.startElement(uri, localName, qName, attributes);
...
if(localName.equals("Category"))
{
// push element into the stack
mTagStack.push(localName);
// get data
int id = Integer.parseInt(attributes.getValue("id"));
String name = attributes.getValue("name");
int numSubcategories = Integer.parseInt(attributes.getValue("numSubcategories"));
// create new Category
if(getDepth()==1)
{
mCategory1 = new Category(id, name);
mCategory1.setSubcategoriesSize(numSubcategories);
mCategory1.setSubcategories(null);
if(mCurrentDepth<getDepth()) mCategories1 = new ArrayList<Category>(); // deeping down so create new list
}
else if(getDepth()==2)
{
mCategory2 = new Category(id, name);
mCategory2.setSubcategoriesSize(numSubcategories);
mCategory2.setSubcategories(null);
if(mCurrentDepth<getDepth()) mCategories2 = new ArrayList<Category>(); // deeping down so create new list
}
else if(getDepth()==3)
{
mCategory3 = new Category(id, name);
mCategory3.setSubcategoriesSize(numSubcategories);
mCategory3.setSubcategories(null);
if(mCurrentDepth<getDepth()) mCategories3 = new ArrayList<Category>(); // deeping down so create new list
}
// debug output
if(mCurrentDepth<getDepth()) Log.d("SAX_TEST", getPath() + " | " + getDepth() + " | DEEPING DOWN");
else if(mCurrentDepth>getDepth()) Log.d("SAX_TEST", getPath() + " | " + getDepth() + " | DEEPING UP");
else if(mCurrentDepth==getDepth()) Log.d("SAX_TEST", getPath() + " | " + getDepth() + " | STAYING");
// set current depth
mCurrentDepth = getDepth();
return;
}
}
public void characters(char[] ch, int start, int length) throws SAXException
{
super.characters(ch, start, length);
...
}
public void endElement(String uri, String localName, String qName) throws SAXException
{
super.endElement(uri, localName, qName);
...
if(localName.equals("Category"))
{
// debug output
Log.d("SAX_TEST", "END OF THE ELEMENT IN DEPTH " + getDepth() + " | " + mCurrentDepth);
// deeping up so set sublist for current category
if(getDepth()!=mCurrentDepth)
{
if(getDepth()==2) mCategory2.setSubcategories(mCategories3);
if(getDepth()==1) mCategory1.setSubcategories(mCategories2);
}
// add current category to list
if(getDepth()==1)
{
mCategories1.add(mCategory1);
}
else if(getDepth()==2)
{
mCategories2.add(mCategory2);
}
else if(getDepth()==3)
{
mCategories3.add(mCategory3);
}
// pop element from stack
mTagStack.pop();
return;
}
}
// debug output - write current path
private String getPath()
{
String buffer = "";
Enumeration<String> e = mTagStack.elements();
while (e.hasMoreElements())
{
buffer = buffer + "/" + (String) e.nextElement();
}
return buffer;
}
// get current depth of stack
private int getDepth()
{
return mTagStack.size();
}
}