Contact Robert Hartung

x Cancel
posted 2 years ago

PHP: simpleXMLElement and (multiple) Namespaces

                <?php
  
  
  // disable errors
  libxml_use_internal_errors();
  
  // your XML String / Source
  $content = file_get_contents('http://www.eslgfx.net/rss/news_default_www_de.xml');
  
  // our root element
  $xml_root = new SimpleXMLElement($content, null, false);
  
  $namespaces = $xml_root->getNamespaces(true);
  
  // if there aren't any namespaces, we use a default one
  // with an empty prefix and no URL for the definition
  
  if(!count($namespaces))
  {
    $namespaces = Array('' => null);
  }
  
  foreach($namespaces AS $prefix => $ns)
  {
    $xml_root->registerXPathNamespace(empty($prefix) ? '__ns' : $prefix, $ns);
  }
  
  $prefix = '';
  if(isset($namespaces['rdf']))
  {
    $prefix = 'rdf';
  }
  
  $list = getXMLChildList($xml_root, $namespaces, $prefix);
  
  echo '<pre>';
  var_dump($list);
  echo '</pre>';
  
  function getXMLChildList(SimpleXMLElement $xml, array $namespaces, $prefix = '', $path = '', $path_dir = '/')
  {
    $list = Array();
    $dname = (!empty($prefix) ? $prefix.':' : '').$xml->getName();
    $name = (!empty($prefix) ? $prefix.':' : '__ns').$xml->getName();
    $path_dir = $path_dir.$name;
    $cpath = $path.'<'.$dname.'>';
    if((string)$xml !== '')
    {
      $list[$path_dir] = $cpath;
    }
    
    foreach($namespaces AS $prefix => $ns)
    {
      foreach($xml->attributes($ns) AS $a)
      {
        $aname = (!empty($prefix) ? $prefix.':' : '').$a->getName();
        $list[$path_dir.'/@'.$aname] = $path.'<'.$dname.'> @'.$aname;
      }
    }
    
    foreach($namespaces AS $prefix => $ns)
    {
      foreach($xml->children($ns) AS $xml_child)
      {
        $x = getXMLChildList($xml_child, $namespaces, $prefix, $cpath.' ', $path_dir.'/');
        $list = array_merge($list, $x);
      }
    }
    
    return array_unique($list);
  }
?>                
Raw

I was working on some parsing of XML Feeds for my CMS as I had a problem with namespaces. I tried a lot to get all child elements (their paths) out of it.

This is the basic code extracted so you can use it right away.

What it does? Well that's quite simple: The code parses a XML document with SimpleXMLElement and returns a list via the function that is an array of key value pairs. Keys are xPath() conform paths you can use to query on a SimpleXMLElement for children. The value is a string giving you the path in some tag style ( @ ns:attribute) including all of the namespaces.

array(19) {
  ["/rdf:RDF"]=>
  string(9) "<rdf:RDF>"
  ["/rdf:RDF/channel"]=>
  string(19) "<rdf:RDF> <channel>"
  ["/rdf:RDF/channel/@rdf:about"]=>
  string(30) "<rdf:RDF> <channel> @rdf:about"
  ["/rdf:RDF/channel/title"]=>
  string(27) "<rdf:RDF> <channel> <title>"
  ["/rdf:RDF/channel/description"]=>
  string(33) "<rdf:RDF> <channel> <description>"
  ["/rdf:RDF/channel/link"]=>
  string(26) "<rdf:RDF> <channel> <link>"
  ["/rdf:RDF/channel/items"]=>
  string(27) "<rdf:RDF> <channel> <items>"
  ["/rdf:RDF/channel/items/rdf:Seq"]=>
  string(37) "<rdf:RDF> <channel> <items> <rdf:Seq>"
  ["/rdf:RDF/channel/items/rdf:Seq/rdf:li/@rdf:resource"]=>
  string(60) "<rdf:RDF> <channel> <items> <rdf:Seq> <rdf:li> @rdf:resource"
  ["/rdf:RDF/channel/dc:date"]=>
  string(29) "<rdf:RDF> <channel> <dc:date>"
  ["/rdf:RDF/item"]=>
  string(16) "<rdf:RDF> <item>"
  ["/rdf:RDF/item/@rdf:about"]=>
  string(27) "<rdf:RDF> <item> @rdf:about"
  ["/rdf:RDF/item/title"]=>
  string(24) "<rdf:RDF> <item> <title>"
  ["/rdf:RDF/item/link"]=>
  string(23) "<rdf:RDF> <item> <link>"
  ["/rdf:RDF/item/description"]=>
  string(30) "<rdf:RDF> <item> <description>"
  ["/rdf:RDF/item/dc:format"]=>
  string(28) "<rdf:RDF> <item> <dc:format>"
  ["/rdf:RDF/item/dc:date"]=>
  string(26) "<rdf:RDF> <item> <dc:date>"
  ["/rdf:RDF/item/dc:source"]=>
  string(28) "<rdf:RDF> <item> <dc:source>"
  ["/rdf:RDF/item/dc:creator"]=>
  string(29) "<rdf:RDF> <item> <dc:creator>"
}
Raw
posted 2 years ago

vhost creating with php5-fcgi for apache2

                    #!/bin/sh
    
    ROOT_WWW="/var/www"
    ROOT_USER="$ROOT_WWW/$1"
    NAME_DOCS="htdocs"    

    useradd -d "$ROOT_WWW/$1" $1
    
    adduser www-data $1
    
    mkdir -p "$ROOT_USER/conf"
    mkdir "$ROOT_USER/$NAME_DOCS"
    mkdir "$ROOT_USER/logs"
    mkdir "$ROOT_USER/tmp"
    mkdir "$ROOT_USER/php-fcgi"
    
    chmod 750 "$ROOT_USER"
    chown "root:$1" $ROOT_USER
    chown -R "$1:$1" "$ROOT_USER/$NAME_DOCS"
    chown "$1:$1" "$ROOT_USER/conf"
    chown "$1:$1" "$ROOT_USER/tmp"
    chown "$1:$1" "$ROOT_USER/logs"
    chown "$1:$1" "$ROOT_USER/php-fcgi"
    chmod -R 750 "$ROOT_USER/$NAME_DOCS"
    chmod 750 "$ROOT_USER/tmp"
    chmod 750 "$ROOT_USER/logs"
    chmod 750 "$ROOT_USER/php-fcgi"
    chmod 550 "$ROOT_USER/conf"
    
    cp php.ini "$ROOT_USER/conf/"
    # in my php.ini I set --VHOST-- to wherever the vhost belongs e.g:
    # open_basedir = /var/www/--VHOST--/htdocs/:/var/--VHOST--/tmp/
    # upload_tmp_dir = /var/www/--VHOST--/tmp
    # session.save_path = /var/www/--VHOST--/tmp
    
    sed 's/--VHOST--/$1/g' "$ROOT_USER/conf/php.ini" > TMPFILE && mv TMPFILE "$ROOT_USER/conf/php.ini"
    rm TMPFILE
    
    
    chown $1:$1 "$ROOT_USER/conf/php.ini"
    chmod 440 "$ROOT_USER/conf/php.ini"
    
    cat > $ROOT_USER/php-fcgi/php-fcgi-starter << EOF
    #!/bin/sh
    PHPRC="$ROOT_USER/conf/"
    export PHPRC
    export TMPDIR=$ROOT_USER/tmp
    exec /usr/bin/php5-cgi
    EOF
    
    chown $1:$1 $ROOT_USER/php-fcgi/php-fcgi-starter
    
    chmod 750 $ROOT_USER/php-fcgi/php-fcgi-starter
    
    chattr +i -V $ROOT_USER/php-fcgi/php-fcgi-starter
    
    cat > /etc/apache2/sites-enabled/$1 << EOF
    <VirtualHost *:80>
    ServerAdmin webmaster@$1
    ServerName $1
    ServerAlias www.$1
    SuexecUserGroup $1 $1
    AddHandler fcgid-script .php
    DocumentRoot "$ROOT_USER/$NAME_DOCS"
    DirectoryIndex index.htm index.html index.php
    <Directory "$ROOT_USER/$NAME_DOCS">
          AllowOverride all
      Options Indexes MultiViews FollowSymLinks +ExecCGI
      FCGIWrapper $ROOT_USER/php-fcgi/php-fcgi-starter .php
      Order allow,deny
      allow from all
    </Directory>
    ErrorLog $ROOT_USER/logs/error.log
    LogLevel warn
    CustomLog $ROOT_USER/logs/access.log combined
    ServerSignature On
    </VirtualHost>
    EOF
    
    echo "CREATED VHOST $1"
    
    # You should do:
    # passwd $1                
Raw

This is a little script I wrote a few minutes ago, it makes it really easy to create vhosts in your preferred directory :-) Saved me a lot of time so far!

posted 2 years ago

MySQL alternative for MySQL's built in RAND() function

http://www.rhcms.de/blog.php

DROP PROCEDURE IF EXISTS proc_get_random_post_id;

DELIMITER //

CREATE PROCEDURE proc_get_random_post_id (IN cnt INT)
BEGIN
  DECLARE max_id INTEGER;

  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    CALL proc_get_random_post_id(cnt);
  END;

  IF cnt >= 1 THEN
    DROP TEMPORARY TABLE IF EXISTS random;
    CREATE TEMPORARY TABLE random ( post_id INTEGER(11) unsigned, UNIQUE KEY(post_id) );

    insert_loop : LOOP
      IF cnt < 1 THEN
        LEAVE insert_loop;
      END IF;

      SELECT MAX(post_id) FROM posts INTO max_id;

      INSERT INTO random
        SELECT
         p.post_id
        FROM
          posts AS p
        JOIN
          (SELECT (RAND() *  max_id) AS random_id) AS r
        WHERE
          p.post_id >= r.random_id
        ORDER BY
          p.post_id
        LIMIT
          1;

      SET cnt = cnt - 1;
    END LOOP insert_loop;

    SELECT post_id FROM random;
  END IF;
END//

DELIMITER ;
Raw