SAX ´Â xml-dev ¸ÞÀϸµ ¸®½ºÆ®¸¦ ÅëÇÑ ¸¹Àº »ç¶÷µéÀÇ Á¶¾ðÀ» ÅëÇØ, David Megginson ÀÌ °³¹ßÇÏ¿´´Ù. SAX ´Â XML ÀÇ ÆÄ½Ì¿¡ ´ëÇØ À̺¥Æ®-±¸µ¿(event-driven) ÀÎÅÍÆäÀ̽º¸¦ °®´Â´Ù. SAX ¸¦ »ç¿ëÇϱâ À§Çؼ, ÀûÀýÇÑ ÀÎÅÍÆäÀ̽º°¡ ¼±¾ðµÈ ÆÄÀ̽ã Ŭ·¡½º ÀνºÅϽº¸¦ Çϳª »ý¼ºÇϰí, ÀÌ ¿ÀºêÁ§Æ®ÀÇ ÀûÀýÇÑ ¸Þ½îµå¸¦ È£ÃâÇÔÀ¸·Î¼ ÆÄ½ÌÀ» ÇÏ°Ô µÈ´Ù.
ÀÌÀü ¹öÀüÀÇ ¹®¼¿¡¼´Â SAX1 À» ¼³¸íÇÏ¿´Áö¸¸, À̹ø ÇÏ¿ìÅõ¿¡¼´Â SAX ¹öÀü 2 (SAX2) ¸¦ °¡Áö°í ¼³¸íÀ» ÇÑ´Ù.
SAX ´Â óÀ½ºÎÅÍ ³¡±îÁö ±¸¼ºµÈ XML ¹®¼¸¦ Àоîµé¿©, ´Ù¸¥ ¹®¼·Î º¯È¯ÇϱâÀ§ÇØ ¿¬»êÇϰųª, ±× ¹®¼ÀÇ Á¤º¸µéÀ» Á¤¸®ÇÏ´Â (¿¹¸¦µé¾î ƯÁ¤ ¿ä¼ÒÀÇ Æò±Õ°ªµîÀ» °è»êÇÏ´Â ÀÛ¾÷) µî¿¡ ÀûÇÕÇÏ´Ù. ±×·¯³ª, °£´ÜÇÑ ¿ä¼ÒÀÇ ³»¿ëÀ̳ª ¼Ó¼ºÀ» ´Ù¸¥°ªÀ¸·Î ¹Ù²Ù´Â µîÀÇ °£´ÜÇÑ ¸ñÀû¿¡ »ç¿ëµÉ¼ö´Â À־, ÁßøµÈ ¾î¶°ÇÑ ¿ä¼ÒµéÀ» ±³È¯ÇÑ´Ù´øÁö ÇÏ´Â º¹ÀâÇÑ ¿¬»êµîÀÇ ¹®¼±¸Á¶ º¯È¯¿¡´Â ÀûÇÕÇÏÁö ¾Ê´Ù. ¿¹¸¦ µé¾î, SAX ¸¦ »ç¿ëÇÏ¿© ¼Ó¼º°ªÀÌ 'greek'ÀÎ ¾î¶² ¿ä¼ÒÀÇ ³»¿ëÀ» Greek ¹®ÀÚ·Î º¯È¯ÇÏ´Â µîÀÇ ÀÛ¾÷¿¡´Â ÀûÇÕÇÏÁö¸¸, Àüü Ã¥ÀÇ Ã©Å͸¦ Àç¹èÄ¡ÇÑ´Ù´Â µîÀÇ ÀÛ¾÷Àº ÀûÇÕÇÏÁö ¾Ê´Ù.
SAX ÀÇ ÀåÁ¡Àº ¼Óµµ¿Í ´Ü¼øÇÔ¿¡ ÀÖ´Ù. ¸¸ÈÃ¥µéÀ» ³ª¿Çϱâ À§ÇÑ DTD °¡ Á¤ÀǵǾî ÀÖ´Ù°í °¡Á¤Çϰí, ´ç½ÅÀÌ ´ç½ÅÀÌ ¼ÒÀåÇϰí ÀÖ´Â ¸¸ÈÃ¥Áß¿¡¼ ÀúÀÚ(writer)°¡ Neil Gaiman ÀÎ ¸ðµç°ÍÀ» ãÀ¸·Á ÇÑ´Ù°í ÇÏÀÚ. ÀÌ·¯ÇÑ Æ¯Á¤ÇÑ ÀÏ¿¡ ´ëÇØ¼, °Ë»ö¿¡ °ü·ÃÀÌ ¾ø´Â ¹Ì¼ú°¡(artist)³ª ÆíÁýÀÚ(editor), ä»ö°¡(colourist) µîÀÇ ¿ä¼Ò¿¡ ´ëÇÑ ¼³¸íÀ» È®ÀåÇÒ ÇÊ¿ä´Â ¾ø´Ù. ±×·¯¹Ç·Î ÀÌ·²¶§¿¡´Â ¿ä¼ÒÁß ÀúÀÚ(writer)¸¦ Á¦¿ÜÇÑ ³ª¸ÓÁö ¿ä¼Ò´Â ¹«½ÃÇϵµ·Ï Ŭ·¡½º ÀνºÅϽº¸¦ ÀÛ¼ºÇÏ¸é µÈ´Ù.
¶Ç´Ù¸¥ ÀÌÁ¡Àº, ƯÁ¤½ÃÁ¡¿¡ ÀÖ¾î ¸ðµç ¹®¼ÀÇ ³»¿ëÀ» ¸Þ¸ð¸®¿¡ ¿Ã¸®Áö ¾Ê¾Æµµ µÈ´Ù´Â °ÍÀÌ´Ù. À̰ÍÀº ¸Å¿ì Å« ¹®¼¸¦ ó¸®ÇÒ¶§ ¸Å¿ì À¯¿ëÇÒ°ÍÀÌ´Ù.
SAX ´Â 4°³ÀÇ ±âº»ÀûÀÎ ÀÎÅÍÆäÀ̽º¸¦ °¡Áö°í ÀÖ´Ù. SAX ¸¦ µû¸£´Â ÆÄ¼´Â µ¥ÀÌÅ͸¦ ó¸®Çϱâ À§ÇØ ´Ù¾çÇÑ ¸Þ½îµå¸¦ È£ÃâÇϸç, ÀÌ·¯ÇÑ ÀÎÅÍÆäÀ̽º¸¦ Áö¿øÇÏ´Â ¾î¶°ÇÑ ¿ÀºêÁ§Æ®µµ ³Ñ°Ü¹ÞÀ» ¼ö ÀÖ´Ù. ±×·¯¹Ç·Î, ´ç½ÅÀÇ ÀÛ¾÷¿¡ ´ç½ÅÀÇ ¾îÇø®ÄÉÀ̼ǰú °ü·ÃµÈ ÀÎÅÍÆäÀ̽º¸¦ ÀÌ¿ëÇÏ¸é µÉ°ÍÀÌ´Ù.
SAX ÀÎÅÍÆäÀ̽º´Â ´ÙÀ½°ú °°´Ù.:
Interface | Purpose |
ContentHandler | ÀÌ ÀÎÅÍÆäÀ̽º´Â SAX ÀÇ ÇÙ½ÉÀ¸·Î, ÀϹÝÀûÀÎ ¹®¼ À̺¥Æ®¸¦ À§ÇÑ È£ÃâÀÌ´Ù. ÀÌ ¸Þ½îµå´Â ¹®¼ÀÇ ½ÃÀÛ, ¿ä¼ÒÀÇ ½ÃÀÛ°ú ³¡, ¿ä¼Ò°¡ Æ÷ÇÔÇÏ´Â ³»¿ëÀÇ ¹®ÀÚ¸¦ ¸¸³¯¶§ È£ÃâÀ» ÇÑ´Ù. |
DTDHandler | ±âº»ÀûÀÎ ÆÄ½Ì¿¡ ÀÖ¾î ¿ä±¸µÇ´Â DTD À̺¥Æ®¸¦ Çڵ鸵Çϱâ À§ÇØ È£ÃâµÈ´Ù. Áï Ç¥±â¹ý(XML spec section 4.7)°ú ÆÄ½ÌµÇÁö ¾Ê´Â ¿£Æ¼Æ¼(entity) ¼±¾ð(XML spec section 4)À»¸¸³¶§ È£ÃâÀ» ÇÑ´Ù. |
EntityResolver | ¿ÜºÎ ¿£Æ¼Æ¼¸¦ ÂüÁ¶Çϱâ À§ÇÏ¿© »ç¿ëµÈ´Ù.¸¸ÀÏ ¹®¼¿¡ ¿ÜºÎ ¿£Æ¼Æ¼ ÂüÁ¶°¡ ¾ø´Ù¸é, ÀÌ ÀÎÅÍÆäÀ̽º¸¦ ½ÇÇàÇÒ Çʿ䰡 ¾øÀ»°ÍÀÌ´Ù. |
ErrorHandler | ¿¡·¯¸¦ ó¸®Çϱâ À§ÇØ È£ÃâÇÑ´Ù.ÆÄ¼´Â ¸ðµç °æ°í¿Í ¿¡·¯¸¦ º¸°íÇϱâ À§ÇØ ÀÌ ÀÎÅÍÆäÀ̽º¸¦ ÅëÇØ ¸Þ½îµå¸¦ È£ÃâÇÑ´Ù. |
ÆÄÀ̽ãÀº ÀÎÅÍÆäÀ̽º¿¡ ´ëÇÑ ³»¿ëÀ» Áö¿øÇÏÁö ¾ÊÀ¸¹Ç·Î À§ÀÇ ÀÎÅÍÆäÀ̽º´Â ÆÄÀ̽ã Ŭ·¡½º·Î ÀçÁ¤ÀÇ µÇ¾î¾ß ÇÑ´Ù. ±âº»ÀûÀ¸·Î ¸Þ½îµå´Â ¾Æ¹«·± Àϵµ ÇÏÁö ¾Ê´Â´Ù.(¸Þ½îµåÀÇ ³»¿ëÀº ÆÄÀ̽ãÀÇ pass ¸í·ÉÀ¸·Î µÇ¾îÀÖ´Ù.) ±×·¯¹Ç·Î ¾îÇø®ÄÉÀ̼ǿ¡¼ »ç¿ëÇÏÁö ¾Ê´Â ¸Þ½îµå¿¡ ´ëÇØ¼´Â ´Ü¼øÈ÷ ¹«½ÃÇØ ¹ö¸®¸é µÈ´Ù.
¿©±â SAX ¸¦ »ç¿ëÇÏ´Â ½´µµÄÚµåÀÇ ¿¹°¡ ÀÖ´Ù :
# Çڵ鷯 Ŭ·¡½ºÀÇ Á¤ÀÇ from xml.sax import Contenthandler, ... class docHandler(ContentHandler): ... # Çڵ鷯 Ŭ·¡½ºÀÇ ÀνºÅϽº »ý¼º dh = docHandler() # XML parser »ý¼º parser = ... # ÆÄ¼¿¡ Çڵ鷯 ÀνºÅϽº¸¦ ÁöÁ¤ parser.setContentHandler(dh) # ÆÄÀÏ ÆÄ½Ì; Çڵ鷯 ¸Þ¼Òµå°¡ È£ÃâµÉ°ÍÀÌ´Ù. parser.parse(sys.stdin) |
¸¸ÈÃ¥µé¿¡ ´ëÇÑ Á¤º¸¸¦ ÀúÀåÇÏ´Â °£´ÜÇÑ XML Æ÷¸Ë¿¡ ´ëÇØ »ý°¢Çغ¸ÀÚ. Çѱǿ¡ ´ëÇÑ °£´ÜÇÑ ¹®¼°¡ ¿©±â ÀÖ´Ù. :
<collection> <comic title="Sandman" number='62'> <writer>Neil Gaiman</writer> <penciller pages='1-9,18-24'>Glyn Dillon</penciller> <penciller pages="10-17">Charles Vess</penciller> </comic> </collection> |
XML ¹®¼´Â ¹Ýµå½Ã ÇϳªÀÇ ÃÖ»óÀ§ ¿ä¼Ò¸¦ °¡Áö°í ÀÖ¾î¾ßÇÑ´Ù. ¿©±â¼´Â "collection" ÀÌ ÃÖ»óÀ§ ¿ä¼ÒÀÌ´Ù. À̰ÍÀº ÇϳªÀÇ ÀÚ½Ä ¿ä¼ÒÀÎ comic À» °®´Â´Ù. comic ¿ä¼ÒÀÇ ¼Ó¼ºÀ¸·Î Ã¥ÀÇ Á¦¸ñ(title)°ú ¹øÈ£(number)°¡ ÁÖ¾îÁ³À¸¸ç, ÀúÀÚ(writer)¿Í ¹Ì¼ú°¡(artist)¿¡ ´ëÇØ Çϳª ¶Ç´Â ±×ÀÌ»óÀÇ ÀÚ½ÄÀ» °¡Áö°í ÀÖ´Ù. ÇϳªÀÇ °£Ç๰(issue)¿¡ ´ëÇØ ¿©·¯¸íÀÇ ¹Ì¼ú°¡(artist) ³ª ÀúÀÚ(writer)°¡ ÀÖÀ»¼ö ÀÖ´Ù.
°£´ÜÇÑ »óÅ·Π½ÃÀÛÀ» ÇØº¸ÀÚ : FindIssue ¶ó À̸§ Áö¾îÁø ¹®¼Çڵ鷯(document handler)´Â ÁÖ¾îÁø °£Ç๰ÀÌ Ä÷¢¼Ç ³»¿¡ ÀÖ´ÂÁö ã´ÂÀÏÀ» ÇÒ°ÍÀÌ´Ù.
from xml.sax import saxutils class FindIssue(saxutils.DefaultHandler): def __init__(self, title, number): self.search_title, self.search_number = title, number |
DefaultHandler Ŭ·¡½º´Â ³×°³ÀÇ ÀÎÅÍÆäÀ̽º - ContentHandler, DTDHandler, EntityResolver, ±×¸®°í ErrorHandler ¿¡¼ »ó¼ÓÀ» ¹Þ´Â´Ù. À̰ÍÀº ¸ðµç°ÍÀ» ÇϳªÀÇ Å¬·¡½º ³»¿¡¼ »ç¿ëÇÏ±æ ¿øÇÒ¶§ »ç¿ëÇÏ´Â ¹æ¹ýÀÌ´Ù. ¸¸ÀÏ °¢°¢ÀÇ ¸ñÀû¿¡ µû¶ó Ŭ·¡½º¸¦ ³ª´©±æ ¿øÇϰųª, ÇϳªÀÇ ÀÎÅÍÆäÀ̽º¸¸À» ¼±¾ðÇÏ±æ ¿øÇÑ´Ù¸é, °¢ ÀÎÅÍÆäÀ̽º¿¡ µû¶ó °¢°¢ ¼ºêŬ·¡½º¸¦ ¸¸µé¼ö ÀÖ´Ù. ÀÌÁß¿¡ ¾î´À ¹æ¹ýÀÌ ´õ ÁÁ´Ù°í ÇÒ¼ö´Â ¾øÀ¸¸ç, ¹«¾ùÀ» ÇÒ°ÍÀΰ¡¿¡ µû¶ó ÀûÀýÇÑ ¹æ¹ýÀ» ÅÃÇÏ¸é µÉ°ÍÀÌ´Ù.
Ŭ·¡½º°¡ °Ë»öÀ» Çϱâ À§Çؼ, ÀνºÅϽº´Â ¹«¾ùÀ» °Ë»öÇÒ°ÍÀÎÁö¸¦ ¾Ë¾Æ¾ßÇÑ´Ù. ã±â¸¦ ¿øÇÏ´Â title °ú ¹ßÇ๰ ¹øÈ£´Â FindIssue »ý¼ºÀÚ¿¡°Ô °Ç³»Áö°í, ÀνºÅϽºÀÇ ÀϺηΠÀúÀåµÉ°ÍÀÌ´Ù.
ÀÚ ÀÌÁ¦ ½ÇÁ¦·Î µ¿ÀÛÀ» ÇÏ´Â ÇÔ¼ö¸¦ »ìÆìº¸µµ·Ï ÇÏÀÚ. ÀÌ °£´ÜÇÑ ÀÛ¾÷Àº ´ÜÁö ÁÖ¾îÁø ¿ä¼ÒÀÇ ¼Ó¼ºÀ» »ìÆìº¸´Â °ÍÀ̹ǷΠstartElement ¸Þ¼Òµå°¡ ÀûÇÕÇÒ °ÍÀÌ´Ù.
def startElement(self, name, attrs): # comic ¿ä¼Ò°¡ ¾Æ´Ï¸é ¹«½ÃÇ϶ó. if name != 'comic': return # title °ú number ¼Ó¼º¿¡ ´ëÇØ °Ë»öÀ» ÇÑ´Ù. title = attrs.get('title', None) number = attrs.get('number', None) if title == self.search_title and number == self.search_number: print title, '#'+str(number), 'found' |
startElement() ´Â ¹®¼ÀÇ ¸ðµç ¿ä¼Ò¸¦ ¸¸³¯¶§¸¶´Ù È£ÃâµÈ´Ù. startElement() ÇÔ¼öÀÇ Ã³À½¿¡ 'Starting element:' ¸¦ Ãâ·ÂÇϵµ·Ï Äڵ带 Áý¾î³Ö´Â´Ù¸é, ´ÙÀ½°ú °°Àº Ãâ·ÂÀ» º¸°Ô µÉ°ÍÀÌ´Ù.
Starting element: collection Starting element: comic Starting element: writer Starting element: penciller Starting element: penciller |
½ÇÁ¦ Ŭ·¡½º¸¦ »ç¿ëÇϱâ À§Çؼ, parser ¿Í FindIssue ÀνºÅϽº¸¦ »ý¼ºÇϰí À̵éÀ» ¿¬°áÇϰí, ÀԷ°ªÀ» ÆÄ½ÌÇϵµ·Ï ÆÄ¼¸¦ È£ÃâÇÏ´Â ÃÖ»óÀ§ Äڵ尡 ÇÊ¿äÇÏ´Ù.
from xml.sax import make_parser from xml.sax.handler import feature_namespaces if __name__ == '__main__': # ÆÄ¼ÀÇ »ý¼º parser = make_parser() # ÆÄ¼¿¡°Ô XML À̸§¿µ¿ªÀº ¹«½ÃÇϵµ·Ï ÀüÇÑ´Ù. parser.setFeature(feature_namespaces, 0) # handler ÀÇ »ý¼º dh = FindIssue('Sandman', '62') # ÆÄ¼¿¡ ¿ì¸®°¡ ¸¸µç Çڵ鷯¸¦ »ç¿ëÇϵµ·Ï ÀüÇÑ´Ù. parser.setContentHandler(dh) # ÀÔ·ÂÀ» ÆÄ½ÌÇÑ´Ù. parser.parse(file) |
make_parser Ŭ·¡½º´Â ÆÄ¼¸¦ ¸¸µå´Â ÀÛ¾÷À» ÀÚµ¿À¸·Î ÇØÁØ´Ù. ÆÄÀ̽㿡´Â ÀÌ¹Ì ¿©·¯°¡Áö XML ÆÄ¼°¡ Á¸ÀçÇϸç, ¾ÕÀ¸·Îµµ ¸¹Àº ÆÄ¼°¡ Ãß°¡µÉ ¿¹Á¤ÀÌ´Ù. ÆÄÀ̽ã 1.5 ¹öÀü¿¡ ÀÖ´Â xmllib.py ´Â Ưº°È÷ ºü¸£Áö´Â ¾ÊÁö¸¸, ÇöÀçµµ »ç¿ë°¡´ÉÇÏ´Ù. xmllib.py ÀÇ ¼Óµµ¸¦ °³¼±ÇÑ ¹öÀüÀÌ xml.parsers ¿¡ Æ÷ÇԵǾîÀÖ´Ù. xml.parsers.expat ¸ðµâÀº Áö±Ý±îÁö´Â °¡Àå ºü¸£¸ç, °¡´ÉÇÏ´Ù¸é À̰ÍÀÌ ¼±ÅõȴÙ. make_parser ´Â ¾î¶² ÆÄ¼°¡ »ç¿ë°¡´ÉÇÑÁö¸¦ °áÁ¤Çϰí, °¡Àå ºü¸¥ ÆÄ¼¸¦ ¼±ÅÃÇÑ´Ù. ±×·¯¹Ç·Î, °¢ ÆÄ¼µéÀÌ ¾î¶»°Ô ´Ù¸¥Áö¿¡ ´ëÇØ¼´Â »ç¿ëÀÚ°¡ ¾Ë°í ÀÖ¾î¾ß ÇÒ Çʿ䰡 ¾ø´Ù. (make_parser ¿¡ ´ç½ÅÀÌ »ç¿ëÇϱ⸦ ¿øÇÏ´Â ÆÄ¼ ¸®½ºÆ®¸¦ ¾Ë·ÁÁÙ¼öµµ ÀÖ´Ù.)
SAX2 ¿¡¼ºÎÅÍ, XML À̸§¿µ¿ª(namespace)ÀÌ Áö¿øµÈ´Ù. ¸¸ÀÏ À̸§¿µ¿ª ÇÁ·Î¼¼½ÌÀÌ ¿¢Æ¼ºê µÇ¾îÀÖ´Ù¸é, startElement ´ë½Å startElementNS ÀÌ È£ÃâµÈ´Ù. content Çڵ鷯°¡ À̸§¿µ¿ª¿¡ ´ëÇÑ ¸Þ¼Òµå¸¦ Á¤ÀÇÇÏÁö ¾Ê¾Ò´Ù¸é, À̸§¿µ¿ª 󸮸¦ ÇÏÁö ¾Ê°Ú´Ù°í ¿ä±¸ÇÏ´Â °ÍÀÌ´Ù. ÀÌ ¼³Á¤ÀÇ ±âº»Àº ÆÄ¼¿¡¼ ÆÄ¼·Î ¼öÁ¤À» °¡ÇÑ´Ù. ±×·¯¹Ç·Î ¾ÈÀüÇÑ °ªÀ¸·Î ¼³Á¤À» Çϴ°ÍÀÌ ÁÁ´Ù.
ÆÄ¼ ÀνºÅϽº¸¦ »ý¼ºÇÑ ÈÄ, setContentHandler ¸¦ È£ÃâÇÏ¿© ÆÄ¼¿¡°Ô »ç¿ëÇÒ Çڵ鷯¸¦ ³Ñ°ÜÁØ´Ù.
¿¹Á¦ XML ¹®¼¸¦ À§ÀÇ Äڵ忡 ´ëÀÔÇϸé, Ãâ·ÂÀ¸·Î 'Sandman #62 found' °¡ ³ª¿Ã°ÍÀÌ´Ù.
ÀÌÁ¦ À§ÀÇ Äڵ忡 ¾Æ·¡ÀÇ ÆÄÀÏÀ» ÀÔ·ÂÀ¸·Î ³Ö¾îº¸ÀÚ:
<collection> &foo; <comic title="Sandman" number='62'> </collection> |
&foo; ¿£Æ¼Æ¼´Â ¾Ë·ÁÁöÁö ¾ÊÀº°ÍÀ̸ç, comic ¿ä¼Ò´Â ´ÝÈ÷Áö ¾Ê¾Ò´Ù. (¸¸ÀÏ ºó ³»¿ëÀ» °®´Â´Ù ÇÏ´õ¶óµµ ">" ·Î ´Ý±â Àü¿¡ "/" ¸¦ »ç¿ëÇÏ¿©¾ß ÇÑ´Ù.) ÀÌ·¯ÇÑ °á°ú·Î, SAXParseException ÀÌ ¹ß»ýÇÑ´Ù.
xml.sax._exceptions.SAXParseException: undefined entity at None:2:2 |
ErrorHandler ÀÎÅÍÆäÀ̽ºÀÇ ±âº»ÄÚµå´Â ¾î¶°ÇÑ ¿¡·¯¿¡ ´ëÇØ¼µµ ÀÚµ¿ÀûÀ¸·Î ¿¹¿Ü¸¦ ¹ß»ý½ÃŲ´Ù; ¸¸ÀÏ ÀÌ·¯ÇÑ ¿¡·¯Ã³¸®¸¦ ¿øÇÑ´Ù¸é, ¿¡·¯ Çڵ鷯¸¦ ¼öÁ¤ÇÒ Çʿ䰡 ¾øÀ»°ÍÀÌ´Ù. ¶ÇÇÑ, ÀÚ±â ÀڽŸ¸ÀÇ ErrorHandler ÀÎÅÍÆäÀ̽º³ª, error(), fatalError() ¿¡ ´ëÇÑ ÃÖ¼ÒÇÑÀÇ ¿À¹ö¶óÀ̵带 ¸¸µé¼öµµ ÀÖ´Ù. °¢ ¸Þ¼Òµå´Â ÃÖ¼Ò·Î ÇÑ ÁÙ Àϼöµµ ÀÖ´Ù. warning, error, fatalError ¿¡ ´ëÇÑ ErrorHandler ÀÎÅÍÆäÀ̽º ¸Þ½îµå´Â ¸ðµÎ ÇϳªÀÇ ÀÎÀÚ°ª - exception ÀνºÅϽº¸¦ °®´Â´Ù. exception Àº Ç×»ó SAXException ÀÇ ¼ºêŬ·¡½ºÀ̸ç, str() ¸¦ ÀÌ¿ëÇÏ¿© ÀÐÀ»¼öÀÖ´Â ¹®Á¦Á¡À» ¼³¸íÇÏ´Â ¿¡·¯ ¸Þ¼¼Áö·Î ¸¸µé¼öÀÖ´Ù.
´ÙÀ½Àº, ¿©·¯°¡Áö ¿¡·¯¹ß»ý »óȲÀ» Àç¼³Á¤Çϱâ À§ÇØ, ¼¼°¡ÁöÁß ÇϳªÀÇ ¸Þ¼Òµå¸¦ ¿¹¿Ü¸¦ Ãâ·ÂÇϵµ·Ï Á¤ÀÇÇÏ¿´´Ù:
def error(self, exception): import sys sys.stderr.write("\%s\n" \% exception) |
ÀÌ Á¤ÀÇ¿¡ ÀÇÇϸé, Ä¡¸íÀûÀÌÁö ¾ÊÀº error ´Â ¿¡·¯ ¸Þ¼¼Áö¸¦ Ãâ·ÂÇÏ°Ô µÇÁö¸¸, Ä¡¸íÀûÀÎ ¿¡·¯(fatal error) ´Â Æ®·¹À̽º¹é(traceback)À» »ý¼ºÇÏ´Â ÀÏÀ» °è¼ÓÇÒ °ÍÀÌ´Ù.
ƯÁ¤ ÀúÀÚ(author) °¡ ¾´ ¸ðµç ¹ßÇ๰(issue) ¸¦ Ãâ·ÂÇÏ´Â, Á¶±Ý´õ º¹ÀâÇÑ ÀÛ¾÷À» ÇØº¸ÀÚ. Let's tackle a slightly more complicated task, printing out all issues written by a certain author. À̰ÍÀº ÀúÀÚÀÇ À̸§ÀÌ <writer>Peter Milligan</writer> °ú °°ÀÌ writer ¿ä¼ÒÀÇ ³»ºÎ¿¡ Á¸ÀçÇϹǷÎ, ¿ä¼ÒÀÇ ³»¿ëÀ» °Ë»öÇØ¾ßÇÑ´Ù.
ÀÌ·¯ÇÑ °Ë»öÀº ´ÙÀ½°ú °°Àº ¾Ë°í¸®ÁòÀ» µû¶ó 󸮵ȴÙ:
startElement ¸Þ½îµå´Â Á¶±Ý´õ º¹ÀâÇÏ°Ô µÈ´Ù. comic ¿ä¼Ò¿¡ ´ëÇØ, °Ë»ö±âÁØ¿¡ ÀûÇÕÇÑ comic À» ³ªÁß¿¡ ã±âÀ§ÇØ, Çڵ鷯´Â title °ú number ¸¦ ÀúÀåÇÏ¿©¾ßÇÑ´Ù. writer ¿ä¼Ò¿¡ ´ëÇØ¼´Â, inWriterContent Ç÷¡±×¸¦ ÂüÀ¸·Î ¼³Á¤Çϰí, writerName ¼Ó¼ºÀ» ºó ¹®ÀÚ¿·Î ¼³Á¤ÇÑ´Ù.
XML ű׹ÛÀÇ ¹®ÀÚµé(Characters)À» ó¸®ÇÏ¿©¾ß ÇÑ´Ù. inWriterContent °¡ ÂüÀ̸é, ÀÌ ¹®ÀÚµéÀ» writeName ¹®ÀÚ¿¿¡ Ãß°¡ÇÑ´Ù.
writer ¿ä¼Ò°¡ ³¡³ª¸é, writerName ¼Ó¼º¾ÈÀÇ ¸ðµç ¿ä¼ÒÀÇ ³»¿ëÀ» ¼öÁýÇѰÍÀÌ µÈ´Ù. ±×·¯¹Ç·Î, ã°íÀÚÇÏ´Â name °ú µ¿ÀÏÇѰÍÀÎÁö °Ë»çÇϰí, ¸¸ÀÏ ¸Â´Â´Ù¸é, ÀÌ comic ¿¡ ´ëÇÑ Á¤º¸¸¦ Ãâ·ÂÇÑ´Ù. ´Ù½Ã inWriterContent ¸¦ °ÅÁþÀ¸·Î ¼³Á¤ÇÑ´Ù.
¿©±â¿¡ ù¹øÂ° ºÎºÐÀÇ Äڵ尡 ÀÖ´Ù.
from xml.sax import ContentHandler import string def normalize_whitespace(text): "¹®ÀÚ¿¿¡¼ Áߺ¹ÀûÀ¸·Î ³ªÅ¸³ª´Â °ø¹é¹®ÀÚ(whitespace)¸¦ Á¦°ÅÇÑ´Ù." return string.join(string.split(text), ' ') class FindWriter(ContentHandler): def __init__(self, search_name): # ã°íÀÚ ÇÏ´Â À̸§À» ÀúÀåÇÑ´Ù. self.search_name = normalize_whitespace(search_name) # Ç÷¡±×¸¦ °ÅÁþ(false)À¸·Î ÃʱâÈÇÑ´Ù. self.inWriterContent = 0 def startElement(self, name, attrs): # comic ¿ä¼ÒÀ̸é, title °ú issue ¸¦ ÀúÀåÇÑ´Ù. if name == 'comic': title = normalize_whitespace(attrs.get('title', "")) number = normalize_whitespace(attrs.get('number', "")) self.this_title = title self.this_number = number # writer ¿ä¼ÒÀÇ ½ÃÀÛÀ̸é, Ç÷¡±×¸¦ ¼³Á¤ÇÑ´Ù. elif name == 'writer': self.inWriterContent = 1 self.writerName = "" |
startElement() ¸Þ¼Òµå¿¡ ´ëÇØ¼´Â ÀÌÀü¿¡ ¼³¸íÇÏ¿´´Ù. ÀÌÁ¦ ¿ä¼ÒÀÇ ³»¿ëÀ» ¾î¶»°Ô ó¸®ÇÏ´ÂÁö º¸ÀÚ.
normalize_whitespace() ÇÔ¼ö´Â ¸Å¿ì Áß¿äÇϹǷÎ, Äڵ峻¿¡ À̰ÍÀ» »ç¿ëÇÏ¿©¾ß ÇÑ´Ù. XML Àº °ø¹é¹®ÀÚ(whitespace) ¿¡ ¸Å¿ì ¹Î°¨ÇÏ´Ù; ´ç½ÅÀº ´ç½ÅÀÌ ¿øÇÏ´Â °÷¿¡ ¿©ºÐÀÇ °ø¹é°ú °³Ç๮ÀÚµéÀ» Æ÷ÇÔ½Ãų ¼ö ÀÖ´Ù. À̰ÍÀº ¼Ó¼º°ªÀ̳ª ¿ä¼ÒÀÇ ³»¿ëÀ» ºñ±³Çϱâ Àü¿¡, °ø¹é¹®ÀÚ¸¦ Á¤»óÀûÀ¸·Î ¸¸µé¾î¾ß ÇÔÀ» ÀǹÌÇÑ´Ù; ¸¸ÀÏ µÎ°³ÀÇ ¿ä¼ÒÀÇ ³»¿ëÀÌ ´Ù¸¥ ¼öÀÇ °ø¹é¹®ÀÚ¸¦ °®´Â´Ù¸é, ºñ±³¿¬»êÀº À߸øµÈ °á°ú¸¦ ¸¸µé¾î³¾ °ÍÀÌ´Ù.
def characters(self, ch): if self.inWriterContent: self.writerName = self.writerName + ch |
characters() ¸Þ½îµå´Â XML ű׹ÛÀÇ ¹®ÀÚµéÀ» ¸¸³¯¶§ È£ÃâµÈ´Ù. ch ´Â ¹®ÀÚµéÀÇ ½ºÆ®¸µÀÌÁö¸¸, ¹Ýµå½Ã ¹ÙÀÌÆ® ½ºÆ®¸µÀΰÍÀº ¾Æ´Ï´Ù; ÆÄ¼´Â ¹®¼ÀÇ ÀϺκÐÀÎ ¹öÆÛ ¿ÀºêÁ§Æ®¸¦ Á¦°øÇϰųª, À¯´ÏÄÚµå ¿ÀºêÁ§Æ®¸¦ °Ç³»ÁÖ°Ô µÈ´Ù(ÆÄÀ̽ã 2.0 ÀÇ expat ÆÄ¼). parsers may also provide a buffer object that is a slice of the full document, or they may pass Unicode objects (as the expat parser does in Python 2.0).
¸ðµç ¹®ÀÚµéÀÌ ÇѹøÀÇ ÇÔ¼ö È£Ãâ·Î ó¸®µÈ´Ù°í °¡Á¤ÇÏÁö ¸»±â ¹Ù¶õ´Ù. À§ÀÇ ¿¹¸¦ µé¾îº¸¸é, "Peter Milligan" ¶ó´Â ¹®ÀÚ¿¿¡ ´ëÇØ ÇѹøÀÇ characters() È£ÃâÀÌ Àְųª, ¶Ç´Â °¢ ¹®ÀÚ¿¡ ´ëÇØ Çѹø¾¿ characters() ÀÇ È£ÃâÀÌ ÀÖÀ» ¼ö ÀÖ´Ù. ´õ¿í Çö½ÇÀûÀ¸·Î, ¸¸ÀÏ ³»¿ëÀÌ "Wagner & Seagle" °ú °°ÀÌ ¿£Æ¼Æ¼ ÂüÁ¶¸¦ °¡Áö°í ÀÖ´Ù¸é, ÆÄ¼´Â "Wagner ", ¿£Æ¼Æ¼ ÂüÁ¶¸¦ »ó¡ÇÏ´Â "&", ±×¸®°í " Seagle" ¿¡ ´ëÇØ °¢ ¼¼¹øÀÇ ¸Þ¼Òµå È£ÃâÀ» ÇÏ°Ô µÈ´Ù.
FindWriter ÀÇ µÎ¹øÂ° °úÁ¤¿¡¼, characters() ´Â ´ÜÁö inWriterContent ¸¦ °Ë»çÇϰí, ÀÌ °ªÀÌ ÂüÀ̸é, ¹®ÀÚ¸¦ ¹®ÀÚ¿¿¡ Ãß°¡ÇÏ´Â ÀÛ¾÷À» ÇÑ´Ù.
¸¶Áö¸·À¸·Î, writer ¿ä¼Ò°¡ ³¡³¯¶§, Àüü À̸§ÀÌ ¼öÁýµÉ°ÍÀ̰í, À̰ÍÀ» ¿ì¸®°¡ ã°íÀÚÇÏ´Â À̸§°ú ºñ±³ÇÏ°Ô µÈ´Ù.
def endElement(self, name): if name == 'writer': self.inWriterContent = 0 self.writerName = normalize_whitespace(self.writerName) if self.search_name == self.writerName: print 'Found:', self.this_title, self.this_number |
´Ù¸¥ °ø¹é¹®ÀÚ¼ö¿¡ ÀÇÇÑ È¥µ¿À» ¸·±âÀ§ÇØ, normalize_whitespace() ÇÔ¼ö°¡ È£ÃâµÇ¾ú´Ù. À̰ÍÀº ÀÌ DTD ³»¿¡¼´Â, ÀÌ ¿ä¼Ò°¡ °¡Áö°í ÀÖ´Â °ø¹é¹®ÀÚ°¡ Áß¿äÇÏÁö ¾Ê±â ¶§¹®ÀÌ´Ù.
¸¶Ä§ ű×(End tags)´Â ¼Ó¼ºÀ» °¡Áú¼ö ¾øÀ¸¹Ç·Î, ¿©±â¿¡´Â attrs ÀÎÀÚ°¡ ¾ø´Ù. "<arc name="Season of Mists"/>" ¿Í °°ÀÌ ¼Ó¼ºÀ» °®´Â ºó ű״Â, startElement() ¸¦ È£ÃâÇÑ ÈÄ ¹Ù·Î endElement() ¸¦ È£ÃâÇÑ´Ù.
XXX ¿ÜºÎ ¿£Æ¼Æ¼ 󸮴 ¾î¶»°Ô ÇÒ°ÍÀΰ¡? ±×µé¿¡ ´ëÇÑ Ã³¸®°¡ Ưº°È÷ ÇÊ¿äÇѰ¡?
SAX ȨÆäÀÌÁö´Ù. ¿©±â¿¡´Â °¡Àå ÃÖ½ÅÀÇ ¸í¼¼¼¿Í ´Ù¾çÇÑ ¾ð¾î¿Í Ç÷§Æû»óÀÇ SAX µµ±¸ ¸®½ºÆ®°¡ ÀÖ´Ù. ÇöÀç´Â ÀÚ¹Ù Áß½ÉÀûÀ¸·Î µÇ¾îÀÖ´Ù.