我可以對以下問題使用一些指導。整個「不允許使用XML庫」部分讓我陷入循環。謝謝!Java XML解析
創建一個Java程序,以XML作爲輸入,分析輸入和 所有的元素名稱寫入與標籤縮進 其嵌套級別控制檯。你應該處理xml屬性,但是你不需要顯示或者解釋它們。無需 處理CDATA或任何xml處理指令。不允許使用xml 庫。
我可以對以下問題使用一些指導。整個「不允許使用XML庫」部分讓我陷入循環。謝謝!Java XML解析
創建一個Java程序,以XML作爲輸入,分析輸入和 所有的元素名稱寫入與標籤縮進 其嵌套級別控制檯。你應該處理xml屬性,但是你不需要顯示或者解釋它們。無需 處理CDATA或任何xml處理指令。不允許使用xml 庫。
標識使用測試驅動開發在這裏
我會寫測試,如
的assertEquals("測試",解析(" <測試/ > "));
的assertEquals("測試",解析(" <測試> < /測試> "));
的assertEquals("測試\ n \ tfun ",解析(" <測試> <樂趣> < /樂趣> < /測試> "));
等,使他們都通過。
記得處理角落案件和不良xml。
解析你可以這樣做:
1)String.indexOf找到第一(<),並在循環最後一個(>)XML元素和處理裏面是什麼。使用遞歸會讓你有更好的成績。
2)你也可以使用String.split。你可以拆分第一個和最後一個XML元素或使用正則表達式來獲取XML元素內部的內容。如果你知道正則表達式,2a是最容易寫的,但1最好,因爲它的速度更快(你可能看不到它,但聽起來更快),許多老師只關心性能。
我不確定什麼等級會困擾你。
首先,您將迭代所有XML字符。
我個人會使用StringTokenizer。我知道這有些過時,但是你可以很容易地解析你感興趣的兩個角括號字符,你可以設置它返回「Tokens」。
因此,您獲得的每個令牌都是左角,直角或一些沒有角度的字符串。
在XML中,角度不會嵌套,這實際上可以節省很多工作量。所以我們假設你的XML看起來像這樣(在代碼塊之外,我正在將角括號轉換爲parens,因爲我不想輸入所有的&符號廢話,任何對此不舒服的人都可以編輯我的帖子,修復):
<tag var="meh">between</tag>
你的第一令牌是 「<」,然後 「標籤VAR =」 MEH」,然後 「>」,然後 「之間」 時,則 「<」,然後 「/標記」 ,那麼「>」
到目前爲止還不錯
您需要知道,如果您在角括號內或外界知道如何處理您的字符串,請將其作爲布爾值進行跟蹤。由於沒有嵌套,所以一個布爾值就足夠了。
您還需要了解您的標籤嵌套級別。這應該會自動讓你的大腦閃現單詞「Stack」。堆棧是你如何實現嵌套,期限。
所以你的過程是,讀一個令牌。如果它是「<」,則將內部布爾值設置爲true並繼續,如果是「>」,則將布爾值設置爲false並繼續。把這兩個搞定了!你完成了一半!
接下來,如果你是,我寧願實例具有以下屬性的對象:
String tagName
HashMap<String, String> attributes
// Why the heck do angle-brackets correctly display here SO?!?
String value
並將其推入你的籌碼。 (注意,LinkedList有一個Stack API)
所以你會把名字存儲在「tagName」和HashMap中的變量中並繼續。如果是我,這個小類將有一個構造函數接受一個字符串,並且它所用的字符串將是尖括號之間的字符串。它會解析字符串本身並在返回之前存儲tagName和屬性。
如果你這樣做,那麼你的循環,你只是說如果你是「內=真」,並且該值不是一個角括號(你知道它不是,這些案件已被刪除!),然後簡單地說: (哎呀,如果這個「標記」以「/」開始,你必須做一些不同的事情,繼續閱讀)。
非常簡潔易讀,不是嗎?
最後,剩下的一種情況是當你在外面,你的字符串是一個標記。在這種情況下,您知道最近的堆棧條目是除「值」以外填寫的XMLObject。價值應該是你現在的標誌。
你完成了除印刷。
哦,我忘了,當你打你的結束標記,你需要彈出值從堆棧並打印(推開放標籤,彈出關閉標籤)
你可以讓你的縮進級別檢查堆棧的大小(stack.size()應確定要打印多少個選項卡)。
如果你真的要劃分責任,我不得不實施的XMLObject格式化該數據,你想讓它打印方式一個toString,那麼當你到達終點的標籤,所有你需要做的是:
Pop the XMLObject.
Print out stack.size() tabs (use print not println!)
Print XMLObject.toString();
這實際上是您的整個項目(除了實際編碼它的工作外)。
學會通過分析過程來檢查您的數據並開發這樣一個簡單的程序應該很快成爲第二性質。
祝你新生事業順利!
這有點複雜,所以我提出了這個可能性列表。迭代每個令牌,並處理每個案例。我很肯定這涵蓋了所有可能性,如果你把錯誤檢查放在我指定的地方,它實際上就是生產質量(我認爲)。
注意:您實際上無法做到這一點。考慮是否/如果其他語句。
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行,也許2或3,如果你不嵌入stack.push(新的XMLObject(令牌))之類的東西。
我不會提供這麼多,但它比我想象的更復雜,因爲我包括所有的錯誤檢查和東西。
我儘量避免使用真正的java,所以請使用自己的風格!所描述的XMLObject類是一個非常好的主意。習慣於儘可能地創建新類(我從字面上看不到有太多類的代碼)。
這是太多的幫助,但它非常有趣我可能會寫一個XML解析器只是爲了它的地獄。
fyi:尖括號只是在代碼文字之外的Markdown中使用時很痛苦。裏面的代碼文字,他們很直接。 – 2009-09-20 23:02:25
p.s.我會將你的HashMap的名稱從「變量」更改爲「屬性」,因爲屬性就是它們的名稱。 – 2009-09-20 23:05:48
謝謝賈森,修好了!注意:如果不明顯,則不能使用=或==,必須使用.equals作爲字符串。另外,你可能想要在很多東西上調用.trim(例如你的標籤)。去除前導空間和尾隨空間。 – 2009-09-21 00:55:47
有點棘手的情況下要注意的:
<!-- this is a comment-->
/>
結束<element foo='1' bar='2' baz='3' />
標籤)Ug +1好點,我忘了那兩個!猜猜他是否喜歡我的答案,他將不得不爲自己弄清楚這一部分 - 儘管不太難。 – 2009-09-21 01:02:25
只需經過XML文件逐個字符,做你必須做的事情。
設置一些狀態變量(與像等待開始標記,讀取元件名,等待屬性名,讀取屬性值,讀取元件含量值 - 等待結束標記等)。
設置深度計數器(因爲您需要漂亮打印)。
使用狀態變量和當前字符決定如何更改狀態或將新字符添加到目前爲止您已閱讀的內容。
假設您的XML格式良好。
您的實際任務比'XML解析器'聽起來容易得多。
不比XML解析器容易得多 – 2009-09-21 13:23:25
1)請告訴我們你做了什麼,哪部分是錯的。 2)這是作業,是的? – CPerkins 2009-09-20 21:13:35
好吧,好像你被要求寫一個XML解析器! – ennuikiller 2009-09-20 21:14:03
我還沒有開始,但我想就從哪裏開始...... – 2009-09-20 21:15:21