最近在工作中需要在應(yīng)用中外接藍(lán)牙打印設(shè)備,實(shí)現(xiàn)打印功能。大體流程就是把a(bǔ)pp中的數(shù)據(jù)進(jìn)行解析,處理成打印機(jī)的一系列指令。我們采用自定義標(biāo)簽實(shí)現(xiàn)了該功能。例如<dk-prt-text style = "center;">cdcd</dk-prt-text>就代表打印居中文字cdcd。<dk-prt-img src="xx" style="center"/>就是打印一個(gè)居中的圖片。打印過(guò)程的難點(diǎn)就是在處理標(biāo)簽的過(guò)程。
由于打印的過(guò)程不外乎分為打印文字和打印標(biāo)簽,所以可以采取遞歸的方式進(jìn)行處理問(wèn)題,遞歸結(jié)束的標(biāo)志為內(nèi)容字符串的長(zhǎng)度為0;代碼如下:
- (void)parseContent:(NSString *)content command:(Command *)command {
//先判斷可以直接打印的內(nèi)容,即直接打印文字
NSRange rangeOfTagStart = [content rangeOfString:@"<"]
if (rangeOfTagStart.location != NSNotFound && rangeOfTagStart.location) {
//直接在command中添加打印內(nèi)容,代碼忽略
content = [content substringFromIndex:rangeOfTagStart.location];
}else {
//沒(méi)有找到標(biāo)簽,則說(shuō)明都是直接打印的文字,則直接進(jìn)行打印,并設(shè)置content = @“”
return;
}
NSRange rangeOfTagEnd = [content rangeOfString @">"];
NSString *tagString = @"";
if (rangeOfTagEnd.location != NSNotFound) {
//如果存在, 則獲取標(biāo)簽字符串,并對(duì)tagString賦值
}else {
//如果不存在,則直接輸出content
return;
}
//1. 對(duì)tagString進(jìn)行格式合法性判斷,如果格式合法,則進(jìn)行下一步,如果格式不合法,則直接輸出tagString, 然后遞歸調(diào)用方法,進(jìn)行下一步處理。
//2. 獲取tagString中的style屬性值,寫(xiě)入打印命令中
//3. 分別對(duì)不同的標(biāo)簽進(jìn)行處理
//4. 判斷content是否為空,如果為空則發(fā)送command到打印機(jī),如果不為空,則進(jìn)行遞歸處理
}
有些關(guān)鍵的點(diǎn)需要特別注意
-
如何判斷標(biāo)簽的合法性
對(duì)于單個(gè)標(biāo)簽,例如
<dk-prt-img src="xx" style="center"/>,直接使用正則表達(dá)式<dk-prt-img\\s+ src\\s*=\\s*\"[ ^\"]*\"\\s*>就可以搞定了。對(duì)于需要配對(duì)的標(biāo)簽,例如<dk-prt-text style = "center;">cdcd</dk-prt-text>,則處理的時(shí)候,遇到<dk-prt-text style = "center;">你就需要判斷有沒(méi)有和它配對(duì)的</dk-prt-text>標(biāo)簽,相應(yīng)的,遇到</dk-prt-text>標(biāo)簽的時(shí)候,你也需要進(jìn)行判斷。對(duì)于起始標(biāo)簽
<dk-prt-text>, 我想到了類(lèi)似堆棧的方式,設(shè)置了一個(gè)整型變量count,初始值為1。采用遞歸的方式,遍歷該標(biāo)簽之后的字符串,遇到起始標(biāo)簽,則count+1,遇到結(jié)束標(biāo)簽,則count-1,當(dāng)count為0的時(shí)候,結(jié)束遞歸,說(shuō)明找到與之相匹配的結(jié)束標(biāo)簽。如果遍歷結(jié)束,count的值不為0,則說(shuō)明沒(méi)有找到,直接輸出這個(gè)起始標(biāo)簽。
對(duì)于結(jié)束標(biāo)簽的處理<\dk-prt-text>的處理,起始相對(duì)來(lái)說(shuō)更簡(jiǎn)單,也是使用一個(gè)整型變量進(jìn)行計(jì)數(shù),打印一個(gè)起始便簽的時(shí)候+1,打印一個(gè)結(jié)束標(biāo)簽的時(shí)候-1, 打印結(jié)束標(biāo)簽的時(shí)候,先判斷變量是否為0,如果為0,說(shuō)明前面沒(méi)有與之配對(duì)的起始標(biāo)簽,則直接輸出結(jié)束標(biāo)簽的文本。
-
標(biāo)簽內(nèi)屬性的處理。
對(duì)于標(biāo)簽內(nèi)style屬性的處理,要思考兩個(gè)東西,一個(gè)是如何獲取style中的值,另外一個(gè)是style屬性的作用范圍處理。
style值的處理,可以簡(jiǎn)單的使用正則表達(dá)式進(jìn)行處理,style屬性的作用范圍,對(duì)于img這種單個(gè)標(biāo)簽來(lái)說(shuō),打印完圖片就直接結(jié)束了,然后我們直接在打印命令中輸入恢復(fù)默認(rèn)樣式的指令即可。但是對(duì)于text這種有開(kāi)始和結(jié)束的標(biāo)簽,我們要思考標(biāo)簽嵌套的可能,例如<dk-prt-text style="small">hdcd<dk-prt-text>CDCD</dk-prt-text></dk-prt-text>,我的想法是創(chuàng)建一個(gè)可變數(shù)組,遇到一個(gè)<dk-prt-text>,則保存這個(gè)標(biāo)簽中的style屬性值,為空也進(jìn)行保存。遇到一個(gè)\<dk-prt-text>則刪除數(shù)組中的最后一個(gè)元素,使用倒二個(gè)屬性值進(jìn)行設(shè)置處理。如果刪除最后一個(gè)元素后,數(shù)組為空,則使用默認(rèn)的屬性值進(jìn)行設(shè)置。