我可以对以下问题使用一些指导。整个“不允许使用XML库”部分使我陷入循环。谢谢!
创建一个将XML作为输入,解析输入并
将所有元素名称写入带有缩进标签的控制台
它们的嵌套水平。您应该处理xml属性,但不要
必须显示或以其他方式解释它们。没必要
处理CDATA或任何xml处理指令。不使用xml
允许图书馆。
最佳答案
我不确定什么水平困扰着您。
首先,您将遍历所有XML字符。
我个人将使用StringTokenizer。我知道它有些过时了,但是您可以轻松地将其解析为您感兴趣的两个尖括号字符,并将其设置为返回“令牌”。
因此,您获得的每个标记都是左角,直角或一些没有角度的字符串。
在XML中,angle不嵌套,这实际上为您节省了很多工作。
因此,假设您的XML如下所示(在代码块之外,我将尖括号转换为括号,因为我不想键入所有的“&”字符,因此鼓励任何对此不满意的人编辑我的文章并进行修复):<tag var="meh">between</tag>
您的第一个标记是“ <”,然后是“ tag var =“ meh”,然后是“”>”,然后是“ between”,然后是“ <”,然后是“ / tag”,然后是““>”
到现在为止还挺好。
您需要知道是在尖括号内还是在外面,才能知道如何处理弦乐,因此请以布尔值进行跟踪。由于没有嵌套,因此一个布尔值就足够了。
您还需要了解标签的嵌套级别。那应该使您的大脑自动闪烁“堆栈”一词。堆栈是实现嵌套句点的方式。
因此,您的过程是读取令牌。如果为“ <”,则将内部布尔值设置为true并继续;如果为““>”,则将布尔值设置为false并继续。把这两个弄错了!您完成了一半!
接下来,如果您在内部,我将实例化具有以下属性的对象:
String tagName
HashMap<String, String> attributes
// Why the heck do angle-brackets correctly display here SO?!?
String value
并将其推入堆栈。 (请注意,LinkedList具有堆栈API)
因此,您可以将名称存储在“ tagName”中,并将变量存储在HashMap中,然后继续。如果是我,这个小类将有一个采用字符串的构造函数,而采用的字符串将是尖括号之间的字符串。在返回之前,它将解析字符串本身并存储tagName和属性。
如果这样做了,那么循环,您只需说出自己是“ inside = true”并且该值不是尖括号(您知道不是,这些情况已被删除!),然后简单地:
push(new XMLObject(token));
(糟糕的是,如果此时“令牌”以“ /”开头,则您必须做一些不同的事情,继续阅读)。
非常简洁易读,不是吗?
最后,剩下的一种情况是当您在外面并且您的字符串是一个令牌时。在这种情况下,您知道最新的堆栈条目是一个XMLObject,除了“ value”外,该XMLObject已填写。值应该是您现在拥有的令牌。
除了打印,您已经完成。
哦,我忘了,当您点击结束标签时,您需要将值从堆栈中弹出并打印出来(按下以打开标签,弹出以关闭标签)
您可以通过检查堆栈的大小来获得缩进级别(stack.size()应该确定要打印多少个选项卡)。
如果您实际上想划分职责,我将让XMLObject实现一个toString,该toString以您希望打印的方式格式化数据,然后,当到达end标记时,您要做的就是:
Pop the XMLObject.
Print out stack.size() tabs (use print not println!)
Print XMLObject.toString();
这实际上是您的整个项目(除了实际编写代码的繁琐工作之外)。
学会通过检查数据的分析过程并开发一个像这样的简单程序应该很快成为第二自然。
祝您事业蒸蒸日上!
这有点复杂,所以我列出了所有可能性。为每个令牌迭代它,并处理每种情况。我很确定这涵盖了所有可能性,并且如果您在我指定的位置进行错误检查,则实际上将是生产质量(我认为)。
注意:您实际上无法这样做。考虑if / if else语句。
case token = "<" //note, if already "inside", this is an error
if(inside) throw exception // Indicates < tagname <
inside=true;
case token = ">"
if(!inside) throw exception // Indicates > text or not >
inside=false;
case inside = false
stack.peek().setValue(token)
case inside (inside = true)
sub-case token startsWith "!-- & endsWith "--"
comment, ignore
sub-case token startsWith "/" and endsWith "/" and is more than 1 char long
create the object, then act as though you found a close tag
sub-case token = ""
(throw exception/print error/bail! // inside must have a tag!)
sub-case token.startsWtih("/")
create & push
sub-case token doesn't .startWith "/"
sub-sub-case length=1 (just the slash, lazy close tag)
pop & print
sub-sub-case length > 1
print an error unless (stack.peek().getTagName().equals(tagWithoutSlash))
pop & print
就是这样我认为这些情况中的每一种都是1行,如果不嵌套stack.push(new XMLObject(token))之类的,则可能是2或3行。
我不会提供那么多,但是它比我想象的要复杂得多,因为我包括了所有的错误检查和内容。
我尽力避免使用实际的Java,所以请使用您自己的样式!所描述的XMLObject类是一个非常好的主意。养成在任何可能的地方创建新类的习惯(我从没看过太多类的代码)。
这确实有太多帮助,但是我可以为它编写一个XML解析器,真是太有趣了。
关于java - Java XML解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1452023/