The XML Tools plugin for Notepad++ is awesome and does almost everything I need when I'm working with XML files. There are times, however, when I'm working with markup-oriented files that aren't quite valid, or some return from a webapp that is not only not valid, but also extremely squished and ugly to read. Unfortunately, XML Tools will only format valid markup, so I threw this together. I used a script I found at http://xmlpp.codeplex.com/ as a base, then modified it to be a bit more customizable. It automatically grabs Notepad++'s settings to figure out how to format the markup, but the variables to change the settings are at the top if of the script if you'd like to do so.
# Settings for the Notepad++ Script# By default, it grabs your current notepad settings. If you'd prefer something else, however,# you can set them below.## Original script: Copyright (c) 2008, Fredrik Ekholdt, All rights reserved.# Found at http://xmlpp.codeplex.com/__indent_char='\t'ifeditor.getUseTabs()else' '__indent_size=1ifeditor.getUseTabs()elseeditor.getIndent()__width=100ifeditor.getEdgeMode()==EDGEVISUALSTYLE.NONEelseeditor.getEdgeColumn()classxmlpp:importsys,reindent_char=' 'def__pprint_line(self,indent_level,line,width,output):ifline.strip():start=""number_chars=0indent_width=1ifself.indent_char=='\t':indent_width=editor.getTabWidth()forlinrange(indent_level):start+=self.indent_charnumber_chars=number_chars+1try:number_chars=number_charselem_start=re.findall("(\<\W{0,1}\w+:\w+) ?",line)[0]elem_finished=re.findall("([?|\]\]/]*\>)",line)[0]#should not have *attrs=re.findall("(\S*?\=\".*?\")",line)output.write(start+elem_start)number_chars=(len(start)*indent_width)+len(elem_start)forattrinattrs:if(attrs.index(attr)+1)==len(attrs):number_chars=number_chars+len(elem_finished)if(number_chars+len(attr)+1)>width:output.write("\n")foriinrange(len(start+elem_start)+1):output.write(self.indent_char)number_chars=(len(start)*indent_width)+len(elem_start)+1else:output.write(self.indent_char)number_chars=number_chars+1output.write(attr)number_chars=number_chars+len(attr)output.write(elem_finished+"\n")exceptIndexError:#give up pretty print this lineoutput.write(start+line+"\n")def__pprint_elem_content(self,indent_level,line,output=sys.stdout):ifline.strip():forlinrange(indent_level):output.write(self.indent_char)output.write(line+"\n")def__get_next_elem(self,data):start_pos=data.find("<")end_pos=data.find(">")+1retval=data[start_pos:end_pos]stopper=retval.rfind("/")ifstopper<retval.rfind("\""):stopper=-1single=(stopper>-1and((retval.find(">")-stopper)<(stopper-retval.find("<"))))ignore_excl=retval.find("<!")>-1ignore_question=retval.find("<?")>-1ifignore_excl:cdata=retval.find("<![CDATA[")>-1ifcdata:end_pos=data.find("]]>")ifend_pos>-1:end_pos=end_pos+len("]]>")elifignore_question:end_pos=data.find("?>")+len("?>")ignore=ignore_exclorignore_questionno_indent=ignoreorsingle#print retval, end_pos, start_pos, stopper > -1, no_indentreturnstart_pos, \
end_pos, \
stopper>-1, \
no_indentdefget_pprint(self,xml,indent=4,indentchar=' ',width=80):self.indent_char=indentchar"""Returns the pretty printed xml """classout:output=""defwrite(self,string):self.output+=stringout=out()self.pprint(xml,output=out,indent=indent,width=width)docFormat=notepad.getFormatType(notepad.getCurrentBufferID())newLine='\r\n'ifdocFormat==FORMATTYPE.WINelse'\n'returnout.output.replace('\n',newLine)defpprint(self,xml,output=None,indent=4,width=80):"""Pretty print xml. Use output to select output stream. Default is sys.stdout Use indent to select indentation level. Default is 4 """data=xmlindent_level=0start_pos,end_pos,is_stop,no_indent=self.__get_next_elem(data)while((start_pos>-1andend_pos>-1)):self.__pprint_elem_content(indent_level,data[:start_pos].strip(),output=output)data=data[start_pos:]ifis_stopandnotno_indent:indent_level=indent_level-indentself.__pprint_line(indent_level,data[:end_pos-start_pos],width=width,output=output)data=data[end_pos-start_pos:]ifnotis_stopandnotno_indent:indent_level=indent_level+indentifnotdata:breakelse:start_pos,end_pos,is_stop,no_indent=self.__get_next_elem(data)if__name__=='__main__':editor.setText(xmlpp().get_pprint(editor.getText(),indent=__indent_size,indentchar=__indent_char,width=__width))
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The XML Tools plugin for Notepad++ is awesome and does almost everything I need when I'm working with XML files. There are times, however, when I'm working with markup-oriented files that aren't quite valid, or some return from a webapp that is not only not valid, but also extremely squished and ugly to read. Unfortunately, XML Tools will only format valid markup, so I threw this together. I used a script I found at http://xmlpp.codeplex.com/ as a base, then modified it to be a bit more customizable. It automatically grabs Notepad++'s settings to figure out how to format the markup, but the variables to change the settings are at the top if of the script if you'd like to do so.