SitePoint Sponsor

User Tag List

Page 2 of 2 FirstFirst 12
Results 26 to 46 of 46
  1. #26
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Might be useful ? Though I don't use PEAR at the moment

    http://www.devshed.com/Server_Side/P...ees/page1.html

    Also this has some interesting ideas; Part One covers SAX btw

    http://www.devshed.com/Server_Side/X...HP2/page6.html

  2. #27
    SitePoint Member viTxo's Avatar
    Join Date
    May 2003
    Location
    Valencia, Spain
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I just posted my last message and i thought on sotring all tags instances as a Tree, i need to finish some work today, if i have energies and time this night i will look at it

  3. #28
    SitePoint Member viTxo's Avatar
    Join Date
    May 2003
    Location
    Valencia, Spain
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The CVS repository is up at http://www.sourceforge.net/projects/phpmarker
    It is just the initial import, it doesnt support nested tags.
    I will upload there some samples for other, you already know how it works

  4. #29
    SitePoint Member viTxo's Avatar
    Join Date
    May 2003
    Location
    Valencia, Spain
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi again folks,
    what about using xml_parse_into_struct() function to get an tree like structure? I still don't want to use DOMXML.

  5. #30
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nice topic. A while ago, I wanted to create a SAX-based template engine which takes XHTML and XML-compliant tags as input and when it encouters a tag it executes a particular tag handler. I wanted to limit my tags to the following:

    <tpl:attr name="attribute"/>
    <tpl:foreach name="someList" as="element"></tpl:foreach>
    <tpl:if exists="attribute"></tpl:if>

    So I decided to take this approach:

    XMLTemplate (in Python) by Patrick Lioi:
    http://patrick.lioi.net/archive/2003/09/13/162936

    "Dynamic XML Conversion Using the SAX Parser and a Stack":
    http://www.phpbuilder.com/columns/sc...r20030325.php3

    I also ran into the problem of nested tags and how to handle loops. I decided that maybe I could recursively apply the template to the body of the tag when I encounter a loop so that it handles the variables within the loop. I think this would take care of the nested problem for me.

    JT

  6. #31
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by seratonin
    I also ran into the problem of nested tags and how to handle loops. I decided that maybe I could recursively apply the template to the body of the tag when I encounter a loop so that it handles the variables within the loop. I think this would take care of the nested problem for me.
    This is something of a problem with language parsing. If all you are doing is descending into nested tags then a state machine will do the job (a state machine is used in regular expression matching). The trouble is that in a realistic job you will want to gather information as you descend into the tags. You will want to match up this information as you back out of the nesting. A state machine just doesn't cut it.

    I have only done this a couple of times, so what follows should be treated as still experimental.

    You will need a stack machine as you have surmised. You could descend a tag stack recursively, but I found that this mixed up the parsing and semantic interpretation too much. My preferred solution these days is to have an explicit stack in the listener and keep all of the control code there. This leaves the tag objects free to handle the operations. I had better show some interfaces...
    PHP Code:
    class SaxParser {
        function 
    SaxParser(&$listener) { ... }
        function 
    parse($html) { ... }
    }

    class 
    SaxToTemplateFilter {
        function 
    SaxToTemplateFilter(&$listener) { ... }
        function 
    handleTagStart($name$attributes) { ... }
        function 
    handleTagEnd($name) { ... }
        function 
    handleWholeTag($name$attributes) { ... }
        function 
    handleContent($text) { ... }
    }

    class 
    TemplateListener {
        function 
    TemplateListener(&$writer) { ... }
        function 
    passThrough($content) { ... }
        function 
    createSubstitution($key$value) { ... }
        function 
    substitute($key) { ... }
        function 
    loopStart($variable) { ... }
        function 
    loopEnd() { ... }

    (edit: Fixed a code glitch)

    The TemplateListener knows nothing about the incoming language, it could be HTML, XML or plain text. The SaxParser is generic and so you could use it anywhere. The filter converts incoming tags to semantic calls. This is still a state machine, if indeed it needs any state at all, unless you are doing syntax checking. If you are affirming that loop tags match, then you would need to keep a stack. Personally I wouldn't bother, as it's only really needed for nicer error messages.

    The tricky bits are all in the language listener, especially the loop events. Each one need to push a "stack frame" on the stack. If you are adding new substitutions (macros) within the language, then it will have to keep track of these in the frame. Otherwise all you really need is the loop index. When in the first loop we had the command history recorded both in this stack frame and those below it (this can probably be made more efficient). The loop end then replays the stack frame's command history until it finishes and the stack frame is discarded. This approach is much more efficient than reparsing the raw text stream.

    In the template engine we built we also had included files and aliasing of variables and macros, but that's another story.

    Anyway, now the bad news. We never used it . Looping in particular was too slow, even after optimisation. We changed plan.

    A much more effective method is to compile the template into PHP. This way loop tags simply translate into PHP loops, and special tags translate in CustomTag calls. This is actually easier than building a full blown parser and way easier to debug. Deployment (and testing) is more complicated and we needed to learn another language. I don't think I would recommend generating PHP with PHP unless you are very brave. We used XSLT as a quick and dirty prototype. For anything this complicated I would use Haskell or Ruby for production. It still runs as PHP and if you don't have any other languages on the server then build the templates offline and then deploy them.

    Anyway, just my experience so far .

    yours, Marcus
    Last edited by lastcraft; Jan 12, 2004 at 07:51.
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  7. #32
    SitePoint Member viTxo's Avatar
    Join Date
    May 2003
    Location
    Valencia, Spain
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Looks great, I'll post again when I got something working
    If you want to see the code just check the cvs repository: http://www.sourceforge.net/projects/phpmarker

  8. #33
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by viTxo
    Looks great, I'll post again when I got something working
    If you want to see the code just check the cvs repository: http://www.sourceforge.net/projects/phpmarker
    viTxo,

    Could you post some examples on how to use this?

    Matt

  9. #34
    SitePoint Member viTxo's Avatar
    Join Date
    May 2003
    Location
    Valencia, Spain
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, sorry, I'm writing some docs but it will take a few weeks to finish them, i'm studying for my exams
    BTW, here is how to use the template engine:
    index.php
    PHP Code:
    include('lib/TemplateManager.class.php');
    $manager =& TemplateManager::getInstance();
    $manager -> setDirectory('presentation/');
    $view =& $manager -> getTemplate('layout.html''layout');

    $page['title'] = 'Just a title';
    $page['body'] = 'Lorem Ipsum Dolor...';
    $obj =& new DummyClass(); 

    $friend['site'] = '...';
    $friend['description'] = ...;
    $friend['name'] = '...';
    ...
    $friends[0] = $friend;
    ....
    $numbers[0] = 0;
    $numbers[1] = 1;
    $numbers[2] = 2;
    $numbers[3] = 3;
    $numbers[4] = 4;
    $view -> expose('numbers'$numbers );
    $view -> expose('page'$page );
    $view -> expose('object'$obj );
    $view -> expose('friends'$friends );


    $view -> process(); 
    And the template:
    presentation/portal/index.html
    HTML Code:
    <html>
      <head><title>${page.title}</title></head>
      <body>
       <p>${page.body}</p>
     
         <list name="numbers" as="number">
            <img src="/gfx/counter/${number}.png" alt="${number}"/>
         </list>
      
       <ul>
         <list name="friends" as="friend">
            <li><a href="${friend.site}" title="${friend.description}">${friend.name}</a></li>
         </list>
       </ul>
       <p>${object.attribute}</p>
      </body>
    </html>
    You can iterate over scalar, hashmaps and objects lists. Of course, the template engine is not finished hihi
    I still want to code a conditional tag and a text transformation tag (cut, highlight and date formatting)

    I'll post new stuff here.

    read you soon
    vitxo.
    Last edited by viTxo; Jan 25, 2004 at 03:04. Reason: fixed template code

  10. #35
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is the PHP implementation of XMLTemplate from my link above. It uses the standard SAX parser and a stack to handle tag nesting.

    PHP Code:
    <?php
    // PHP Implementation of Patrick Lioi's "XMLTemplate"
    class XMLTemplate {
        var 
    $tagHandler;
        var 
    $parser;
        var 
    $stack = array();

        function 
    XMLTemplate($tagHandler) {
            
    $this->tagHandler $tagHandler;
        }

        function 
    parse($xml) {
            
    array_push($this->stack, array("contents" => ""));
        
            
    $this->parser xml_parser_create("ISO-8859-1");

            
    xml_parser_set_option($this->parserXML_OPTION_CASE_FOLDINGfalse);
            
            
    xml_set_object($this->parser, &$this);
            
    xml_set_element_handler($this->parser"startElement""endElement");
            
    xml_set_character_data_handler($this->parser"characterData");
            
    xml_set_default_handler($this->parser"characterData");
            
            if (!
    xml_parse($this->parser$xml)) {
                die(
    "Error parsing XML.");
            }

            
    xml_parser_free($this->parser);

            
    $first array_pop($this->stack);
            return 
    $first['contents'];
        }
        
        function 
    createTag($name$attrs$contents) {
            
    $buffer "<$name";
            
            foreach (
    $attrs as $attr => $value) {
                
    $buffer .= ' ' $attr '="' $value '"';
            }
        
            if (
    strlen($contents) == 0) {
                
    $buffer .= " />";
            } else {
                
    $buffer .= ">" $contents "</" $name ">";
            }
            
            return 
    $buffer;
        }

        function 
    startElement($parser$name$attrs) {
            
    array_push($this->stack, array("attrs" => $attrs"contents" => ""));
        }
        
        function 
    characterData($parser$cdata) {
            
    $data array_pop($this->stack);
            
    $data['contents'] .= $cdata;
            
    array_push($this->stack$data);
        }    

        function 
    endElement($parser$name) {
            
    $data array_pop($this->stack);
            
            if (
    method_exists($this->tagHandler$name)) {
                
    $buffer call_user_func(array(&$this->tagHandler$name), $data['attrs'], $data['contents']);
            } else {
                
    $buffer $this->createTag($name$data['attrs'], $data['contents']);
            }
            
            
    $sublevel array_pop($this->stack);
            
    $sublevel['contents'] .= $buffer;
            
    array_push($this->stack$sublevel);
        }
    }
    ?>
    The usage is quite simple. Basically, you would create a class where the names of the class's methods are the same as the names of the tags you wanted to replace.

    For example, say you wanted simple variable replacement with a tag such as <variable name="title"/>. You could do something like this:

    PHP Code:
    <?php
    require_once("XMLTemplate.class.php");

    class 
    TagHandler {
        var 
    $vars;

        function 
    set($name$value) {
            
    $this->vars[$name] = $value;
        }

        function 
    variable($attrs$contents) {
            return 
    $this->vars[$attrs['name']];
        }
    }

    $xml file_get_contents("sometemplate.html");

    $handler = new TagHandler;
    $handler->set("title""Insert Title Here");
    $handler->set("message""Hello, world!");

    $template = new XMLTemplate($handler);
    $result $template->parse($xml);

    echo 
    $result;
    ?>
    sometemplate.html:
    Code:
    <html>
      <head>
        <title><variable name="title"/></title>
      </head>
      <body>
        <variable name="message"/>
      </body>
    </html>
    My desire is to limit the tags to simple variables, conditional (which tests for existence of a variable only), and foreach (include and transform might also be handy). I would, of course, also extend it to handle namespaces <tpl:variable name="message"/>.

    In order to implement the foreach tag, I would treat the contents of the foreach tag as a separate "template" which would call $template->parse for each element. Implementing a conditional, would be relatively easy, because I am limiting it to testing presence of a variable only. I am also tempted to implement some sort of attribute value template system similar to what phpmarker is doing.

    JT
    Last edited by seratonin; Jan 12, 2004 at 15:55.

  11. #36
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by seratonin
    Here is the PHP implementation of XMLTemplate from my link above. It uses the standard SAX parser and a stack to handle tag nesting.
    Hey! Awesome. I going to check this out. But is there a way to take care of the "Call-time pass-by-reference" warnings without messing with error_reporting()?

    Matt

  12. #37
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    Hey! Awesome. I going to check this out. But is there a way to take care of the "Call-time pass-by-reference" warnings without messing with error_reporting()?

    Matt
    Where are you seeing these warnings? Please note that I had to change "var" to "variable" because it is a reserved word. I may change the function calling scheme to handleVariableTag so for example <include file="somefile.php" eval="true"/> would be handled by a class with a method name "handleIncludeTag".

    Another note on handling namespaces -- I was thinking about allowing for multiple TagHandlers that get "registered" with the template each one is associated with a particular namespace. The XMLTemplate class would have an associative array of tag handlers where the namespace is the key a reference to the tag handler class is the value.

    JT

  13. #38
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by seratonin
    Where are you seeing these warnings?
    JT
    From some version of php 4 on up, "Call-time pass-by-reference" has been depreciated. So I get warnings when trying to use it.

    matt

  14. #39
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    From some version of php 4 on up, "Call-time pass-by-reference" has been depreciated. So I get warnings when trying to use it.

    matt
    I am using version 4.3.4 without any warnings. What lines are the warnings on? You might be able to suppress these warnings by putting an "@" in front of the "call_user_func" in the endElement method.

    JT

  15. #40
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by seratonin
    I am using version 4.3.4 without any warnings. What lines are the warnings on? You might be able to suppress these warnings by putting an "@" in front of the "call_user_func" in the endElement method.
    JT
    Hey! It's line 19 and 64. I tried using @ but it didn't stop the errors from popping up.

    Matt

  16. #41
    Talk to the /dev/null Theiggsta's Avatar
    Join Date
    Mar 2001
    Location
    Tampa, FL
    Posts
    376
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I tried to make an SAX/DOM XHTML templating engine a while ago to mimic JSP. The farthest I got was a half-implementation because the SAX stacking was not working properly (nested tags were'nt always being accounted for at all) so i'd be interested to checkout some of these experimental systems.
    Aaron "Theiggsta" Kalin
    Pixel Martini
    Ruby and Rails Developer

  17. #42
    SitePoint Member viTxo's Avatar
    Join Date
    May 2003
    Location
    Valencia, Spain
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by seratonin
    Here is the PHP implementation of XMLTemplate from my link above. It uses the standard SAX parser and a stack to handle tag nesting.
    Great implementation, but I got some questions
    how would you deal with a template like this? -Supposing that we got a multi-dimensional array (4 rows, 7 columns) representing a month-
    HTML Code:
    <html>
      <body>
        <table>
        [b]<list name="month" as="week">[/b]
           <tr>
           [b]<list name="week" as="day">[/b]
             <td><variable name="day"/></td>
           [b]</list>[/b]
           </tr>
        [b]</list>[/b]
        </table>
      </body>
    </html>
    The nested tag problem is solved, but would the ListTagHandler class have to instatiate a TagHandler class (or VariableTagHandler class) to replace the value in the template? Now, the XMLTemplate constructor would receive a $tagHandlers array instead of only a handler per template?

    vitxo.

  18. #43
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think the Composite design pattern may have its place here.

    In a ListTagHandler class you need to be able to treat 'regular' variable blocks (<variable name="day"/>) the same way as list blocks, if/else blocks, etc. That's in any *TagHandler class for that matter.

    I'm not sure how exactly your classes work, but perhaps you can get some inspiration from [url=http://www.google.com/search?q=composite+design+pattern&ie=UTF-8&oe=UTF-8&hl=nl&lr=]Google[/google] on the subject.

  19. #44
    SitePoint Member viTxo's Avatar
    Join Date
    May 2003
    Location
    Valencia, Spain
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've been thinking (again ) that I've planned to "compile" my XML language to PHP, to avoid parsing at runtime. So, I just need to care about translating the template special tags to PHP, the compiled template would contain the php presentation logic and i wouldn't need TagHandlers?!

  20. #45
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by viTxo
    I've been thinking (again ) that I've planned to "compile" my XML language to PHP, to avoid parsing at runtime. So, I just need to care about translating the template special tags to PHP, the compiled template would contain the php presentation logic and i wouldn't need TagHandlers?!
    You could use the XMLTemplate class implementation to do the custom tag -> PHP replacement during the "compilation" process.

    As far as handling a list as above, I believe you would have a ListTagHandler as you said which gets called when the end "list" tag is encountered by the parser. The ListTagHandler (which extends TagHandler) would then take the name attribute ($attrs['name']) and find the appropriate array/list from the vars associative array ($this->vars[$attrs['name']]). Then it would loop through each element and create a template for each element of the list you would recursively call template->parse on the contents of the list tag and concatenate the result together. Or you could do as lastcraft suggested and push the work onto a stack and post-process it to avoid recursion.

    JT
    Last edited by seratonin; Jan 16, 2004 at 17:15.

  21. #46
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Basically we're "there" in WACT (I've just sent what I hope will be the first release to "the board" for approval so there may even be that release finally).

    @lastcraft and @captain proton as they're comments pretty much summarized the approach WACT uses (and it works well I think, Jeff having come up with an excellent design).

    We used XML_HTMLSax as the SAX parser on top of which is an XML_Pull implementation which basically means instead of having seperate SAX callback methods, you can handle all XML "events" in a single while loop, allowing you to handle the template as a single steam.

    On encountering each tag, the parser looks up a class to which it delegates the job of "what to do" with the tag, while adding the instance as a child to the tree of objects being built from the template. Each of these objects writes PHP to a compiled template meaning you end up with fast, mainly procedural PHP at runtime.

    The parser loop only has to deal with the current "Tag Object" and it's parent which, as lastcraft mentions, is probably the best way to go (I've tried this kind of thing with SaxFilters before and XUL, but you end up having to "pass around" the current point in the tree which ends up painful).

    Anyway - have a look. Once the release is out, we're looking for developers...


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •