Edgewall Software

Ticket #102: xpointer.diff

File xpointer.diff, 5.9 KB (added by nicoe@…, 15 years ago)

A patch for a naive support of xpointer

  • util.py

     
    243243    :return: the text with tags removed
    244244    """
    245245    return _STRIPTAGS_RE.sub('', text)
     246
     247def xpointer2xpath(xpointer):
     248    """Returns the XPath representation of an XPointer attribute.
     249
     250    >>> xpointer2xpath(None)
     251    '//*'
     252    >>> xpointer2xpath('id1')
     253    "//node()[@id='id1']"
     254    >>> xpointer2xpath('id1/2')
     255    "//node()[@id='id1']/*[2]"
     256
     257    Absolute XPointer expression should also be supported although the current
     258    XPath parser used by genshi does not support them.
     259   
     260    >>> xpointer2xpath('/1/2/3')
     261    '/*[1]/*[2]/*[3]'
     262    """
     263    if xpointer is None:
     264        return '//*'
     265    path = xpointer.split('/')
     266    start = path.pop(0)
     267    if start == '':
     268        xpath = ['']
     269    else:
     270        xpath = ["//node()[@id='%s']" % start]
     271    for segment in path:
     272        xpath.append('*[%s]' % segment)
     273    return '/'.join(xpath)
  • template/base.py

     
    2424import sys
    2525
    2626from genshi.core import Attrs, Stream, StreamEventKind, START, TEXT, _ensure
    27 from genshi.input import ParseError
     27from genshi.input import ParseError, XML
     28from genshi.util import xpointer2xpath
    2829
    2930__all__ = ['Context', 'DirectiveFactory', 'Template', 'TemplateError',
    3031           'TemplateRuntimeError', 'TemplateSyntaxError', 'BadDirectiveError']
     
    467468                        yield event
    468469            else:
    469470                if kind is INCLUDE:
    470                     href, cls, fallback = data
     471                    href, xpointer, cls, fallback = data
    471472                    if isinstance(href, basestring) and \
    472473                            not getattr(self.loader, 'auto_reload', True):
    473474                        # If the path to the included template is static, and
     
    476477                        try:
    477478                            tmpl = self.loader.load(href, relative_to=pos[0],
    478479                                                    cls=cls or self.__class__)
    479                             for event in tmpl.stream:
     480                            xpath = xpointer2xpath(xpointer)
     481                            stream = Stream(tmpl.stream)
     482                            for event in stream.select(xpath):
    480483                                yield event
    481484                        except TemplateNotFound:
    482485                            if fallback is None:
     
    486489                        continue
    487490                    elif fallback:
    488491                        # Otherwise the include is performed at run time
    489                         data = href, cls, list(self._prepare(fallback))
     492                        data = (href, xpointer, cls,
     493                                list(self._prepare(fallback)))
    490494
    491495                yield kind, data, pos
    492496
     
    602606
    603607        for event in stream:
    604608            if event[0] is INCLUDE:
    605                 href, cls, fallback = event[1]
     609                href, xpointer, cls, fallback = event[1]
    606610                if not isinstance(href, basestring):
    607611                    parts = []
    608612                    for subkind, subdata, subpos in self._eval(href, ctxt,
     
    613617                try:
    614618                    tmpl = self.loader.load(href, relative_to=event[2][0],
    615619                                            cls=cls or self.__class__)
    616                     for event in tmpl.generate(ctxt, **vars):
     620                    xpath = xpointer2xpath(xpointer)
     621                    stream = XML(tmpl.generate(ctxt, **vars)).select(xpath)
     622                    for event in stream:
    617623                        yield event
    618624                except TemplateNotFound:
    619625                    if fallback is None:
  • template/markup.py

     
    222222                            raise TemplateSyntaxError('Include misses required '
    223223                                                      'attribute "href"',
    224224                                                      self.filepath, *pos[1:])
    225                         includes.append((include_href, attrs.get('parse')))
     225                        if attrs.get('parse') == 'text' and \
     226                           attrs.get('xpointer') is not None:
     227                            raise TemplateSyntaxError('Include use an xpointer '
     228                                                      'while parsing a text',
     229                                                      self.filepath, *pos[1:])
     230                        includes.append((include_href, attrs.get('parse'),
     231                                         attrs.get('xpointer')))
    226232                        streams.append([])
    227233                    elif tag.localname == 'fallback':
    228234                        streams.append([])
     
    240246                    streams.pop() # discard anything between the include tags
    241247                                  # and the fallback element
    242248                    stream = streams[-1]
    243                     href, parse = includes.pop()
     249                    href, parse, xpointer = includes.pop()
    244250                    try:
    245251                        cls = {
    246252                            'xml': MarkupTemplate,
     
    250256                        raise TemplateSyntaxError('Invalid value for "parse" '
    251257                                                  'attribute of include',
    252258                                                  self.filepath, *pos[1:])
    253                     stream.append((INCLUDE, (href, cls, fallback), pos))
     259                    stream.append((INCLUDE, (href, xpointer, cls, fallback),
     260                                   pos))
    254261                else:
    255262                    stream.append((kind, data, pos))
    256263