Entries tagged as phpRelated tags ant arbit bug fix continuous integration cruisecontrol git github lint phpmd phpundercontrol phpunit release announcement sebastian marek book ezcomponents phpugdo cli npath complexity php5 php_depend pmd software metrics static code analysis tokenizer changes company consulting quality support training checkstyle cyclomatic complexity design quality php_codesniffer quality assurance conference hamburg unconference apache software foundation kore qafoo toby zeta components css customization dashboard java server pages layout phpdoc testing tutorial crazy customer usability torii portal overview pyramid software architecture software design dortmund phpbbq talks elephpant ext/filter phpt unit test fabien potencier pirum fun dbus derick logger optimization performance static_reflection zce zend certified engineer annotations cbo rule set phpug cologne thinkpad sylvester 2007 elger mayflower php_codebrowser thorsten class interface size coupling between objects xml xpath article ipc karlsruhe php-magazin tools xslFriday, March 14. 2008PHP Unconference 2008Sadly, I could not attend last year's PHP Unconference. As I have heard from all attendees, it was a really great event. But this year I will participate and I am looking forward to the upcoming PHP Unconference in Hamburg where I will meet many geeks the first time. Together with Sebastian, I have proposed a talk about the state of the art of quality assurance in PHP. Due to the nature of an unconference nothing is fixed until the unconference is running, but I assume we have a good chances with our talk, because quality assurance seems to be one of the hottest topics at the moment.
It seems that this year a larger/complete delegation of usergroupies from Dortmund will attend. As tobias said earlier, Stay tuned for the Ruhrpott invasion, Hamburg!
Posted by Manuel Pichler
in php, phpugdo, phpundercontrol, planet-php
at
20:51
| Comments (0)
| Trackback (1)
Wednesday, February 6. 2008How reusable, extensible and maintainable is your software?To provide a flexible and extendable software, it is a good OO practice to reduce the dependencies between implementing classes. This could be achieved by developing against abstractions which means both, abstract classes and interfaces. By using abstractions instead of real implementation in the application you provide some sort of contract, that could be used by others to hook into the application with their own classes that fulfill the contract. Except the extensibility of an application a good abstraction reduces the risk of breaks in multiple subsystems when something was changed in a single package. But how to get rid of all these dependencies, doing this by hand will become an impossible job, at least for larger projects. At this point a tool should be used to assist the development process. PHP_Depend is an adaption of the established Java development tool JDepend. This tool shows you the quality of your design in the terms of extensibility, reusability and maintainability. All these facts are influenced by the inter-package dependencies and the package abstraction that PHP_Depend visualizes in form of an abstract/instability chart and as a detailed XML report of all detected dependencies. PHP_Depend calculates the following metrics by counting classes, interfaces and dependencies.
With these values we can create a chart that visualizes the relationship between the instability (I) on the y-axis and the abstraction (A) on the x-axis. Because in a project not each package can achieve the optimal values of A = 1, I = 0 or A = 0, I = 1, we draw a diagonal between the two corners. This line is called the Main sequence and represents an average between abstraction (A) and instability (I). This means that packages near this line have a good mix between abstraction and instability. You can call these packages balanced. Because it is desirable for packages to be close to the Main sequence we have a fifth metric, the package distance (D) from this ideal.
If you are interested in this subject and PHP_Depend you can check out the latest version, including the unit tests, from the subversion repository or simply install the PHP_Depend PEAR package. But be aware this software is at a very early stage. mapi@arwen $ pear channel-discover pear.xplib.de mapi@arwen $ pear install xplib/PHP_Depend-alpha Now you can run PHP_Depend with the following command. pdepend <source-dir> [<output-dir>]
If you are interested in the code coverage follow this link I will close this post with a cite of Robert Martin:
The following sources were used for this post.
Posted by Manuel Pichler
in php, php_depend, phpugdo, phpundercontrol, planet-php, projects
at
17:52
| Comments (9)
| Trackback (1)
Defined tags for this entry: design quality, php, quality assurance, software architecture, software design, software metrics
Saturday, January 19. 2008phpUnderControl 0.3.x releasedYesterday I released version 0.3.(0|1|2) of phpUnderControl. Except bugfixes and enhancements the major change in this new version of phpUnderControl is an ezcGraph replacement of the original cewolf metrics view. For the excellent appearance of the generated graphics I would like to thank kore, who supported me actively with his deep knowledge of the ezcGraph component. Beside the better appearance, the new graph implementation has another advantage, it performs much better than the original cewolf implementation, because cewolf generates graphics in real time, while the new ezcGraph solution generates static graphics during the build process. To integrate the graph generator into your build process, you must alter the <publishers /> elements in the config.xml file. Simply add a CruiseControl execute-publisher that calls the phpUnderControl cli tool with the graph command, as shown in the following example. <cruisecontrol> <project name="php-under-control" buildafterfailed="false"> ... <publishers> ... <execute command="/path/to/phpuc(.php|.bat) graph logs/${project.name}"/> </publishers> </project> </cruisecontrol> The phpUnderControl graph command expects at least the project log directory as argument, it is the directory where CruiseControl stores the merged xml log files. In this default mode phpUnderControl will generate the metric charts for each build into logs/<project-name>/<build-timestamp>/graph directories. If you use a different CruiseControl setup where artifacts are not stored in the logs/ directory you can call the graph command with a second argument that specifies the output directory, for example:
[mapi@arwen /opt/cruisecontrol]$ phpuc graph logs/phpUnderControl \
artifacts/phpUnderControl
Finally I say thanks to Sebastian, because he integrates a new css file for the coverage reports into PHPUnit, that produces a harmonious overall picture between phpUnderControl and the coverage-report. This stylesheet is yet another contribution by kore. All phpUnderControl versions are available thru the phpunit.de pear channel, just type: [mapi@arwen ~]$ pear channel-discover pear.phpunit.de [mapi@arwen ~]$ pear install --alldeps phpunit/phpUnderControl-beta
Posted by Manuel Pichler
in php, phpugdo, phpundercontrol, planet-php
at
19:45
| Comments (11)
| Trackbacks (0)
Defined tags for this entry: continuous integration, cruisecontrol, css, ezcomponents, php, phpundercontrol, phpunit, quality assurance, testing
Wednesday, January 16. 2008Christmas 2007Ok it is a little bit outdated mainly because I have blogged about Sylvester earlier this year, but one of the presents I recieved no more than two weeks ago. It was this nice toy that you can see right next to this paragraph. Many thanks to Tobias who made this really great present to all groupies of the PHP User Group Dortmund
But I got my main geeky christmas present, one of these super, dupper, "everybody has it" ThinkPad notebooks, from my wife. It has really an other taste, nothing wobbles, everything works as expected under linux and I got me to work with this little red dot in the middle of the keyboard. Friday, November 23. 2007phpUnderControl updateI have never thought that phpUnderControl would be so interesting to others. From my point of view there were just a view modifications and extensions for the original CruiseControl setup that integrate some common PHP development tools. But the comprehensive and positive feedback told me something else. To my surprise Sebastian Bergmann asked me one day after the initial release to host the project on his PHPUnit website and I accepted his offer gladly. This means for you that you will find further releases of phpUnderControl on the PHPUnit website and in the related subversion repository. With this backing and positive feedback the development of the next phpUnderControl preview version started the same day. Beside some bugfixes and minor changes the latest phpUnderControl version has now a really nice layout, many thanks to kore who spent his time for this layout during the last UG meeting. Beyond these changes this release integrates the build artifacts of PHPUnit and PhpDocumentor into the CruiseControl user interface. For the upcoming release the planning is focused on an integrated project wizard, that allows an easy setup of custom projects, and support for windows.
Posted by Manuel Pichler
in php, phpugdo, phpundercontrol, planet-php
at
22:53
| Comments (4)
| Trackbacks (2)
Sunday, November 18. 2007First release of phpUnderControlThis is the first release of the phpUnderControl tool. This tool aims to take the first steps with CruiseControl and PHP as easy as possible. phpUnderControl integrates three of the best PHP development tools into CruiseControl, combined with an easy setup routine and a small example project. With the provided XSL-Stylesheets the generated output of PHPUnit, PHP_CodeSniffer and phpDocumentor can be visualized in CruiseControl, as you can see in the following screenshot. Getting startedNow let's take a look how to start with CruiseControl and phpUnderControl. The first things you need is a Java environment and a working installation of CruiseControl. I assume that Java is already installed and so I will not cover this topic here, but I suggest to use an original Java version from SUN instead of some versions bundled with linux distributions, because in combination with compiz or beryl the metrics view can be broken. Getting a working CruiseControl installation is a simple task. Just download one of the provided zip archives, unpack the contents and start the application. Because this initial release of phpUnderControl is only tested with CruiseControl 2.7, I suggest to use this version for the moment. You can download this version, if you click the following link: When the download has finished, just unzip the archive. unzip cruisecontrol-bin-2.7.zip -d /opt/ For a detailed installation description how to install CruiseControl and how to configure it with PHPUnit I recommend an excellent article by Sebastian Nohn and the Continuous Integration chapter from the PHPUnit Pocket Guide written by Sebastian Bergmann. Now, that you have a working CruiseControl, download the phpUnderControl tool from the following url and unpack the archive:
Small bugfix release, I left some system() calls in the source code. Now, you need to change to the phpUnderControl/bin directory and execute the following command to install the required files. All files that the command line tool modifies, are backed up with the file extension .orig. [mapi@frodo bin]$ ./phpuc.php install /opt/cruisecontrol-bin-2.7 Modifying CruiseControl files. File "main.jsp" modified. File "metrics.jsp" modified. File "xsl/buildresults.xsl" modified. Installing new CruiseControl files. File "phpcs.jsp" installed. File "phpunit-pmd.jsp" installed. File "xsl/phpcs.xsl" installed. File "xsl/phpcs-details.xsl" installed. File "xsl/phpdoc.xsl" installed. File "xsl/phphelper.xsl" installed. File "xsl/phpunit-pmd.xsl" installed. File "xsl/phpunit-pmd-details.xsl" installed. Modifying CruiseControl stylesheet. Creating backup of "css/cruisecontrol.css" as "css/cruisecontrol.css.orig". All you need now is an application with that CruiseControl can work. phpUnderControl comes with a little example application which can be installed with the following command. This example doesn't require any version control system installation. Instead it uses a special tag, that CruiseControl provides. [mapi@frodo bin]$ ./phpuc.php example -t ant /opt/cruisecontrol-bin-2.7 Creating required project directories. 1. Creating CruiseControl project dir "projects/php-under-control". 2. Creating Project input dir "php-under-control/source". 3. Creating Project source dir "php-under-control/source/src". 4. Creating Project test dir "php-under-control/source/tests". 5. Creating Project build dir "php-under-control/build". 6. Creating Project log dir "php-under-control/build/logs" 7. Creating API documentation dir "/tmp/php-under-control/api" 8. Creating Coverage dir "/tmp/php-under-control/coverage" Creating example files. Creating file "php-under-control/source/src/Math.php". Creating file "php-under-control/source/tests/MathTest.php". Creating project build file "php-under-control/build.xml". Preparing CruiseControl "/opt/cruisecontrol-bin-2.7/config.xml. 1. Loading "config.xml" data. 2. Backup original "config.xml" as "config.xml.orig". 3. Creating new project configuration. Now change to the /opt/cruisecontrol-bin-2.7 directory and execute the cruisecontrol.sh or cruisecontrol.bat script to start CruiseControl. If you open your browser with this url http://127.0.0.1:8080/buildresults/php-under-control you will see something similar to the next screenshot. PHPUnit features integratedAs mentioned in a previous post Sebastian Bergmann integrated support for Software Metrics and PMD in the PHPUnit 3.2 branch. Because he has used the original PMD format, the generated output was usable for CruiseControl without any modifications. Additionaly he integrated a third party contribution for Copy & Paste Detection that makes finding duplicate code fragments much easier. To show the results of this new report type the phpUnderControl tool provides modified versions of the original files pmd.xsl, pmd-details.xsl and metrics.jsp that can visualize the new records. PHP_CodeSniffer integration
The PEAR package PHP_CodeSniffer makes us PHP developers a present. With this handy tool coding guildline checks have become a really simple task. As a positive reaction on an other article Greg Sherwood, the lead developer of PHP_CodeSniffer, added support for the Checkstyle format to this package. Cool :-), with the upcoming 1.0.0RC3 release of PHP_CodeSniffer this package will work together with CruiseControl without any changes. The following screenshot shows the PHP_CodeSniffer result for the phpUnderControl example. Please note, all these errors are provoked and not the result of bad coding PLEASE NOTE: The current version 1.0.0RC2 has a small bug in the checkstyle output that causes CruiseControl to fail with the Checkstyle report. I hope this will be fixed in the RC3 release, but if you cannot wait just change line 720 in <pear-install>/PHP/CodeSniffer.php from echo ' line="'.$line.' "column="'.$column.'"'; to echo ' line="'.$line.'" column="'.$column.'"'; or you apply the following patch to <pear-install>/PHP/CodeSniffer.php Index: CodeSniffer.php =================================================================== RCS file: /repository/pear/PHP_CodeSniffer/CodeSniffer.php,v retrieving revision 1.55 diff -r1.55 CodeSniffer.php 720c720 < echo ' line="'.$line.' "column="'.$column.'"'; --- > echo ' line="'.$line.'" column="'.$column.'"'; or you modify the build.xml file and use the XSL-Stylesheet from my previous post. phpDocumentor integrationDuring the last user group meeting, while all others were hacking on some stuff. I thought this small javadoc legend in the "Coding violations" view must be fillable with the results of the standard PHP documentation tool phpDocumentor. The current integration is based on text matching onto the command line output of the phpdoc script which is not a perfect solution. For a future release of phpUnderControl there will be a custom implementation of the output converter that will process the documentation errors and warnings. FinallyI hope this post and the phpUnderControl tool helps someone and was interesting for some of the readers. The current version is only tested under linux which means that I cannot say anything about windows, so I would be delighted if someone provides windows phpuc.bat or phpuc.cmd file.
Posted by Manuel Pichler
in php, phpugdo, phpundercontrol, planet-php
at
16:41
| Comments (5)
| Trackback (1)
Friday, November 2. 2007eZ Components book, the best book ever
Yesterday I recieved my copy of the new eZ Components book from my favourite deliverer
On the basis of a single sample application both authors, Kore Nordmann and Tobias Schlitt, take the reader on a journey into the depth of many components and in addition they show many PHP best practices. In my opinion the approach of a single example application is really great, because the readers are not forced to switch between different contexts and code snippets, that allows them to be concentrated on the main topic of the book. What this book makes really special for me is, that I have spend most time during my summer vacation to cross-read all chapters, to propose some changes and to correct some inaccuracies. To be honest the most important part in this book are two small words in the foreword
Saturday, October 27. 2007More QA with CruiseControl and PHP_CodeSnifferI am using CruiseControl for some time now, to run all Unit Tests for a project continuous after each commit. Since Sebastian Bergmann started the development of PHPUnit 3.2 he added support for software metrics and PMD to PHPUnit, that give you further informations about the quality of your source code. These two features are really well integrated into CruiseControl, the only thing you need to do is to comment out the following lines in the main.jsp file. <%-- <cruisecontrol:tab name="pmd" label="PMD"> <%@ include file="pmd.jsp" %> </cruisecontrol:tab> --%> The next thing that is important for each project is the coding standard of a project, a company or at least a single person. Java has a nice tool called Checkstyle that checks all your code against a defined set of rules. I knew this tool really well from my diploma thesis, because I used Checkstyle to check the complete code against the Sun coding standards. Checkstyle is also really good integrated into CruiseControl, so that it checks on each build that your code meets the coding standards.
So what can a PHP developer do, to achieve the same support? This question is answered fast! There is a nice PEAR package that does nearly the same job as Checkstyle. The name of this package is PHP_CodeSniffer. This PEAR package provides a variety of pre defined coding standards like PEAR, ZEND etc., a small cli script <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="no" indent="yes" /> <xsl:template match="/"> <checkstyle> <xsl:apply-templates select="phpcs/*" /> </checkstyle> </xsl:template> <xsl:template match="file"> <file> <xsl:attribute name="name"> <xsl:value-of select="@name" /> </xsl:attribute> <xsl:for-each select="child::*"> <xsl:call-template name="entry" /> </xsl:for-each> </file> </xsl:template> <xsl:template name="entry"> <error> <xsl:attribute name="line"> <xsl:value-of select="@line" /> </xsl:attribute> <xsl:attribute name="severity"> <xsl:value-of select="local-name()" /> </xsl:attribute> <xsl:attribute name="message"> <xsl:value-of select="text()" /> </xsl:attribute> </error> </xsl:template> </xsl:stylesheet>
You have to add the following lines to your ant <?xml version="1.0" encoding="UTF-8"?> <project name="mapi-xplib-de" default="build" basedir="."> ... <target name="checkstyle"> <exec executable="phpcs" output="${basedir}/build/logs/codesniffer.pcs" dir="${basedir}/source"> <arg line="--report=xml --standard=MapiSource --ignore=src/autoload src/" /> </exec> <exec executable="xsltproc" output="${basedir}/build/logs/checkstyle.xml" dir="${basedir}/build/logs"> <arg line="${checkstyle.xslt} ${basedir}/build/logs/codesniffer.pcs" /> </exec> </target> <target name="build" depends="checkout,checkstyle,test" /> ... </project>
PLEASE NOTE I know that ant supports xsl transformation without external exec commands but it doesn't work with my current gcj installation.
Posted by Manuel Pichler
in php, phpugdo
at
19:03
| Comment (1)
| Trackback (1)
Defined tags for this entry: checkstyle, continuous integration, cruisecontrol, php, php_codesniffer, quality assurance
Saturday, August 4. 2007Exploring the MVCDuring the last weeks while I have read some documents about the model view controller pattern (MVC), which seem to be wrong in my eyes or better expressed, which mix and merge different application layers in a wrong way, I decided to write this blog post. Everybody who reads this text should know for what the shortcut MVC stands. It describes the responsibilities and dependencies between model, view and logic in the top level layer of an application. As I understand it, this means all parts in the presentation layer and nothing else. But most documents wrote about business logic, when the topic controller is treated, and this assertion is wrong in my opinion. Business logic and business models aren't part of the presentation layer, they build a further layer in an application. Keeping each layer independent, means that the presentation should know as few as possible about the underlying business logic. Because practice is more understandable than all written text, I would like to explain my thoughts with a little example. The following diagram shows a simple business modell for a product catalog which implements a transaction based product storing. Beside the business classes you can find all possible exceptions in this diagram. The class To insert a new At this point I will ignore the details and the whole environment around these two components and I will concentrate onto the method Now let's take a look at the required logic for an insert operation. What must be done? First we have to get an instance of <?php
public function doAddProduct() { $name = $this->view->getText(); // Create a new product $product = new mpProduct( $name ); // Get the product catalog $catalog = mpProductCatalog::getInstance(); // Create a new transaction $transaction = $catalog->createTransaction( $product ); try { // Start transaction $transaction->begin(); // Add new product to catalog $catalog->addProduct( $product ); // Commit product transaction $transaction->commit(); // Reset input $this->view->setText( "" ); } catch ( mpProductInTransactionException $e ) { // Show error message $this->showDialog( "Transaction Error", $e->getMessage() ); } catch ( mpProductExistsException $e ) { try { // Rollback product transaction $transaction->rollback(); // Show error message $this->showDialog( "Name Error", $e->getMessage() ); } catch ( mpProductTransactionNotOpenException $e ) { // Show error message $this->showDialog( "Transaction Error", $e->getMessage() ); } } } ?> One weak point this example shows very well is that the controller has at least six dependencies to the business model. Since I assume that dependencies between a business model and the controller will occur more than one time in an application, which makes the maintenance of the business model source code very difficult. Another point that can happen is the need of another presentation layer for your complex business model. For web applications this requirement should be resolvable by the choice of a suitable frameworks, but in some situations it's conceivable that is not possible without larger expenditure. So I created a second GTK based presentation layer for the business model. The source code for this gtk frontend can be found here controller, view. If we compare both So! What can be done to solve this problem? The simple answer to this question is, we have to decouple both layers. So we have to implement a simplified model controller(MC) that encapsulates the business model from the MVC. This technology is also well known under the terms Facade or Command. A very good description can be found in the Java J2EE Blueprints. The following listing shows the new domain/business facade. <?php class mpDomainFacade { public function addProduct( $productName ) { // Create a new product $product = new mpProduct( $productName ); // Get the product catalog $catalog = mpProductCatalog::getInstance(); // Create a new transaction $transaction = $catalog->createTransaction( $product ); try { // Start transaction $transaction->begin(); // Add new product to catalog $catalog->addProduct( $product ); // Commit product transaction $transaction->commit(); } catch ( mpProductInTransactionException $e ) { throw new mpDomainException( "Transaction Error", $e->getMessage() ); } catch ( mpProductExistsException $e ) { try { // Rollback product transaction $transaction->rollback(); // Show error message throw new mpDomainException( "Name Error", $e->getMessage() ); } catch ( mpProductTransactionNotOpenException $e ) { // Show error message throw new mpDomainException( "Transaction Error", $e->getMessage() ); } } } } class mpDomainException extends RuntimeException { private $title = ""; public function __construct( $title, $message ) { parent::__construct( $message ); $this->title = $title; } public function getTitle() { return $this->title; } } ?> As you can see this new subsystem encapsulates the whole insert operation. Everything a client has to do is to pass the new product name into the component and the client must care about thrown <?php public function doAddProduct() { $name = $this->view->getText(); // Create a domain Facade $facade = new mpDomainFacade(); try { // Try to add product $facade->addProduct( $name ); // Reset input $this->view->setText( "" ); } catch ( mpDomainException $e ) { $this->showDialog( $e->getTitle(), $e->getMessage() ); } } ?> The produced overhead is really limited, because the new facade uses same method calls as the original implementation. Even if the introduction of own Value-Objects for communication between Controller and Facade, which weren't used in the shown example, would result in an additional overhead, I have the opinion that the presented technology is important for all large and long running application. The modified source code for the controllers and the facade can be found here: facade, web controller, gtk controller. Since there are a many great applications that aren't working with the presented separation and that are very successful, I assume, that some of my readers will not agree with me. It is also possible that the shown technology is more java and not the php way of doing things. But when I was young, I smoked to much java And now I invite you to discuss with me and I close this post with a citation from Arne Nordmann:
Tuesday, July 3. 2007xpathingHave you ever worked with external xml documents where you don't know the hole structure or exactly all the used namespaces? It's a pain. Such a situation occured for one of our user group members, when he had to process a complex rdf document with multiple different xml markups. The following listing shows a modified and simplified version of this rdf document <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="resource" xmlns:br="http://binary.resource/"> <br:length />1024</br:length> </rdf:Description> <rdf:Description rdf:about="meta" xmlns:bm="http://binary.meta/"> <bm:author>Manuel Pichler</bm:author> <bm:published>2007-07-03</bm:published> </rdf:Description> <rdf:Description rdf:about="more" xmlns:bmore="http://binary.more/"> <bmore:more>more and more and more namespaces</bmore:more> </rdf:Description> </rdf:RDF> How would you handle such a structure where you know all or almost all possible markups, but each is optional? The design for the Document Object Model (DOM) assumes that you know all used namespaces in a document. Ok you can use <?php
$dom = new DOMDocument(); $dom->load( "xpath.xml" ); $foundNS = {FNAMEL}">array(); $nodes = $dom->getElementsByTagNameNS( "*", "*" ); foreach ( $nodes as $node ) { if ( $node->namespaceURI === "http://www.w3.org/1999/02/22-rdf-syntax-ns#" ) { continue; } if ( {FNAMEL}">isset( $foundNS[$node->namespaceURI ] ) ) { continue; } $foundNS[$node->namespaceURI] = true; {FNAMEL}">print "ns-prefix: {$node->prefix}, ns-uri: {$node->namespaceURI}\n"; } ?> This could be a good solution for small documents, but consider really large documents with thousands of elements where each element is part of a namespace. This solution would load all these nodes into user land code and check there for an unknown/unvisited namespace which will be very expensive. So we have to find another solution for our problem. And here comes XPath into the play. XPath provides a large set of functions and constructs that help solving this problem. <?php
$dom = new DOMDocument(); $dom->load( "xpath.xml" ); $xp = new DOMXPath( $dom ); $xp->registerNamespace( "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" ); $nodes = $xp->evaluate( "//*[ name(.) = 'rdf:Description' ]/*[ namespace-uri(.) != namespace-uri(..) and namespace-uri(.) != '' and namespace-uri(.) != namespace-uri(preceding-sibling::*)]" ); foreach ( $nodes as $node ) { {FNAMEL}">print "ns-prefix: {$node->prefix}, ns-uri: {$node->namespaceURI}\n"; } ?> What we do here is. We look for the Comments and optimizations are very welcome.
« previous page
(Page 2 of 2, totaling 25 entries)
|
ProjectsFurther stuffCategories |

