Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 16
  1. #1
    New Coder
    Join Date
    Dec 2003
    Posts
    34
    Thanks
    0
    Thanked 0 Times in 0 Posts

    How do I read XML?

    How do I read XML data from a string? I've searched around in a lot of places, even the manual, but couldn't find anything useful. For example, if I had the following:

    Code:
    $x = '<fruits>
       <fruit>
          <type>apple</type>
          <color>red</color>
       </fruit>
       <fruit>
          <type>lemon</type>
          <color>green</color>
       </fruit>
    </fruits>';
    How could I read that? I want to read it from a textbox, where the user manualy puts it in. How can this be done?

    Any help is appreciated. Thanks!

  • #2
    Senior Coder
    Join Date
    Jun 2002
    Location
    frankfurt, german banana republic
    Posts
    1,848
    Thanks
    0
    Thanked 0 Times in 0 Posts
    The function xml_parse() expects a string as input, exactly what you need.
    http://us2.php.net/manual/en/function.xml-parse.php

    You have to set up the parser and the element handler functions too.
    De gustibus non est disputandum.

  • #3
    New Coder
    Join Date
    Dec 2003
    Posts
    34
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thanks for the response. I don't see the example, however. All the examples shown there require a file. What I want to do, is loop through it (the string representing xml data) like it was a record set. Each <fruit> is a record, and its child values are fields inside the record. As it loops, it will be inserting it in the database.

    If anyone could show me or refer to me to some sample code, I'd appreciated. Thanks!

  • #4
    me'
    me' is offline
    Senior Coder
    Join Date
    Nov 2002
    Location
    Warwickshire, England
    Posts
    1,229
    Thanks
    0
    Thanked 0 Times in 0 Posts
    There's an easy way if you know (or are prepared to learn) XSLT.
    Code:
    $files = array (
      '_/xml' => 'xml code here',
      '_/xsl' => 'xslt code here'
    );
    $xh = xslt_create();
    echo xslt_process($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $files);
    You don't have to echo if you don't want to. You could put it into a string and set up a few MySQL queries to get a database up and running.

    To get the xslt functions going, you'll need the Sablotron dll, which your version of PHP probably came with. Check you have expat.dll, sablot.dll and iconv.dll in c:\windows or c:\winnt, and in <root to php>/dlls. Then modify your php.ini file to uncomment the line:

    ;extension=php_xslt.dll

    (uncommenting simply means getting rid of the semicolon). Also, make sure the line

    extension_dir = "C:\Program Files\pdev\php\extensions\"

    points to the correct extension folder. For more info on Sablotron, look at this thread. If you want to learn XSLT, there's a great tutorial at w3schools.
    David House - Perfect is achieved, not when there is nothing left to add, but when there is nothing left to take away. (Antoine de St. Exupery).
    W3Schools | XHTML Validator | CSS Validator | Colours | Typography | HTML&CSS FAQ | Go get Mozilla Now | I blog!

  • #5
    New Coder
    Join Date
    Dec 2003
    Posts
    34
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Sounds like a good way to do it. Nice and short but I'm working off a web host that doesn't give me access to the php.ini file, so that wouldn't work. Good way to do it though, I'll have to keep that in mind.

  • #6
    me'
    me' is offline
    Senior Coder
    Join Date
    Nov 2002
    Location
    Warwickshire, England
    Posts
    1,229
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Do they have a list of extensions currently installed? The XSLT functions may already by accessible to you.
    David House - Perfect is achieved, not when there is nothing left to add, but when there is nothing left to take away. (Antoine de St. Exupery).
    W3Schools | XHTML Validator | CSS Validator | Colours | Typography | HTML&CSS FAQ | Go get Mozilla Now | I blog!

  • #7
    Senior Coder
    Join Date
    Jun 2002
    Location
    frankfurt, german banana republic
    Posts
    1,848
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Originally posted by jessjenn
    Thanks for the response. I don't see the example, however. All the examples shown there require a file.
    They do, but they read a portion (a string) out of each file and feed that string to xml_parse(). You just have to strip the file part from the examples in your case, since the XML isn't coming from a file, as it usually does.

    What I want to do, is loop through it (the string representing xml data) like it was a record set. Each <fruit> is a record, and its child values are fields inside the record. As it loops, it will be inserting it in the database.
    If you want to use SAX parsing to process your XML document, you have to take care of the all the record-building stuff and looping yourself. You can only provide functions for the parser to be called when an element is found, left, text is found etc. Below is such a script (a quick, adjust to your needs):

    PHP Code:
    $x '<fruits>
       <fruit>
          <type>apple</type>
          <color>red</color>
       </fruit>
       <fruit>
          <type>lemon</type>
          <color>green</color>
       </fruit>
    </fruits>'
    ;

    $fruits = array();
    $current '';

    $parser xml_parser_create();

    xml_parser_set_option($parserXML_OPTION_CASE_FOLDINGfalse);
    xml_set_element_handler($parser'startElement''endElement');
    xml_set_character_data_handler($parser'charHandler');

    function 
    startElement(&$parser$name$attributes) {
        global 
    $fruits$current;
        if (
    $name == 'fruit') {
            
    $fruits[] = array();        
        }
        
        if (
    in_array($name, array('type''color'))) {
            
    $fruits[count($fruits) - 1][$name] = '';
            
    $current $name;
        } 
    }

    function 
    endElement(&$parser$name) {
        
    //    empty
    }

    function 
    charHandler(&$parser$data) {
        global 
    $fruits$current;
        if (
    in_array($current, array('type''color')) ) {
            
    $fruits[count($fruits) - 1][$current] = $data;
            
    $current '';
        }    
    }

    xml_parse($parser$x);
    var_dump($fruits); 
    If you need to know parent-child node relations while parsing, perhaps the DOM XML extension is more suited to your needs? Although it's not a default extension and probably not installed on your host.
    De gustibus non est disputandum.

  • #8
    New Coder
    Join Date
    Dec 2003
    Posts
    34
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Originally posted by me'
    Do they have a list of extensions currently installed? The XSLT functions may already by accessible to you.
    Nope they have nothing like that installed.

  • #9
    New Coder
    Join Date
    Dec 2003
    Posts
    34
    Thanks
    0
    Thanked 0 Times in 0 Posts
    mordred, excellent response! Thanks for the sample. It works beautiful. How complicated would it be if I wanted to read an argument in a tag? Let's say I had my original data but wanted to add an id in all the <fruit> tags:
    Code:
    <fruit id="34">
          <type>apple</type>
          <color>red</color>
    </fruit>
    Thanks. If it's too much trouble, it's ok, you helped me enough with the sample code.

  • #10
    New Coder
    Join Date
    Dec 2003
    Posts
    34
    Thanks
    0
    Thanked 0 Times in 0 Posts
    mordred, how come in your code, I can't have & > < characters between the tags? When I have:

    Code:
    <something>I like M & Ms and soda</something>
    the "&" and what follows disappears. Any thoughts? I escape it with entities and nothing. Thanks.
    Last edited by jessjenn; 01-04-2004 at 05:43 PM.

  • #11
    me'
    me' is offline
    Senior Coder
    Join Date
    Nov 2002
    Location
    Warwickshire, England
    Posts
    1,229
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Use the character entities instead:
    &amp;amp; = &
    &amp;lt; = <
    &amp;gt; = >

    If you have your own DTD, you could specify it as CDATA as well (only works if the tag can never contain other tags)
    Originally posted by jessjenn
    Nope they have nothing like that installed.
    Shame, XSLT parsing is so much easier than with expat.
    David House - Perfect is achieved, not when there is nothing left to add, but when there is nothing left to take away. (Antoine de St. Exupery).
    W3Schools | XHTML Validator | CSS Validator | Colours | Typography | HTML&CSS FAQ | Go get Mozilla Now | I blog!

  • #12
    Senior Coder
    Join Date
    Jun 2002
    Location
    frankfurt, german banana republic
    Posts
    1,848
    Thanks
    0
    Thanked 0 Times in 0 Posts
    me', I was under the impression that XSLT is used to transfrom one XML document into another one. Ok, HTML is an option, and plain text too. You could create your SQL plain text query via XSLT, but honestly, I've never seen it done anywhere... and from a gut feeling I would say it looks like a lot of hassle.

    My point is mainly that sometimes the generation of another document doesn't solve your problem, if you need the actual values as a data structure in your application. You'd still have to parse the generated document anew to read/process it. For these issues SAX and DOM are more suited, IMNSHO. jessjenn mentioned something about database insertion, so I guess XSLT is not really helpful here. Errh, I mean "would be helpful", because the host is as backwards as most are. Agree with your opinion that it's a shame, but not because expat is more difficult to use.
    De gustibus non est disputandum.

  • #13
    Senior Coder
    Join Date
    Jun 2002
    Location
    frankfurt, german banana republic
    Posts
    1,848
    Thanks
    0
    Thanked 0 Times in 0 Posts
    jessjenn, to get the attributes of parse tag, you can access the "attributes" parameter passed to the function you register as the start-element-handler. In my example this function is called startElement (duh!). A var_dump() printing attribute values is included in the example below.

    About the entities... that's due to a little bug in the sample code. Quick hacks almost always work under the "type,run,throw it away" workflow pattern....

    A slightly revamped version is here. The decisive change was made in charHandler, it concatenates the data instead of assigning it.

    PHP Code:
    $x '<fruits>
       <fruit id="foo">
          <type>apple</type>
          <color>red</color>
       </fruit>
       <fruit>
          <type>lemon is &amp; a green &lt; hat</type>
          <color>green</color>
       </fruit>
    </fruits>'
    ;

    $fruits = array();
    $current '';

    $parser xml_parser_create();

    xml_parser_set_option($parserXML_OPTION_CASE_FOLDINGfalse);
    xml_set_element_handler($parser'startElement''endElement');
    xml_set_character_data_handler($parser'charHandler');

    function 
    startElement(&$parser$name$attributes) {
        global 
    $fruits$current;
        
        
    $current '';
        
        
        if (
    count($attributes)) {
            
    var_dump($attributes);
        }
        
        if (
    $name == 'fruit') {
            
    $fruits[] = array();        
        }
        
        if (
    in_array($name, array('type''color'))) {
            
    $fruits[count($fruits) - 1][$name] = '';
            
    $current $name;
        } 
    }

    function 
    endElement(&$parser$name) {
        global 
    $current;
        
    $current '';
    }

    function 
    charHandler(&$parser$data) {
        global 
    $fruits$current;
        if (
    in_array($current, array('type''color')) ) {
            
    $fruits[count($fruits) - 1][$current] .= $data;        
        }    
    }

    function 
    entityHandler(&$parser$data) {
        global 
    $fruits$current;
        if (
    in_array($current, array('type''color')) ) {
            
    $fruits[count($fruits) - 1][$current] = $data;
            
    $current '';
        }    
    }

    xml_parse($parser$x);
    var_dump($fruits); 
    De gustibus non est disputandum.

  • #14
    New Coder
    Join Date
    Dec 2003
    Posts
    34
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Originally posted by me'
    Use the character entities instead:
    &amp;amp; = &
    &amp;lt; = <
    &amp;gt; = >
    I tried that and nothing. Strange. My solution is putting the string within <![CDATA[ $string ]]>. It works well, I don't have to escape those characters but I think I have to escape brackets.

    If I have something like:
    Code:
    <![CDATA[ 11-Nov-2003 ]car & ><<><>< < ]]>
    the " 11-Nov-2003 ]" doesn't get displayed, just what follows the "]" before "car" - so I'm thinking maybe you have to escape brackets. Is this true? What do you think.

  • #15
    me'
    me' is offline
    Senior Coder
    Join Date
    Nov 2002
    Location
    Warwickshire, England
    Posts
    1,229
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Originally posted by mordred
    Agree with your opinion that it's a shame, but not because expat is more difficult to use.
    It certainly can be, I wrote an XML parsing algorithm first in PHP using expat that failed miserably for some stupid reason or another. IMO, using XSLT is more suited to the problem, as it must parse the file first before it can transform it. Also, the code is a lot shorter and it can reside more naturally in two different files for ease of editing. That's my opinion though, I'm sure expat beats XSLT hands down in some cases.

    jessjen: just a long shot as it didn't work before, but try it's entitiy, &amp;#93;?
    David House - Perfect is achieved, not when there is nothing left to add, but when there is nothing left to take away. (Antoine de St. Exupery).
    W3Schools | XHTML Validator | CSS Validator | Colours | Typography | HTML&CSS FAQ | Go get Mozilla Now | I blog!


  •  
    Page 1 of 2 12 LastLast

    Posting Permissions

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