ID:               28807
 User updated by:  rmolier at more-it dot com
 Reported By:      rmolier at more-it dot com
-Status:           Open
+Status:           Closed
 Bug Type:         DOM XML related
 Operating System: Fedora Core 1+2 / RHEL AS 3
 PHP Version:      4.3.6/4.3.2/4.3.4
 New Comment:

Finally (after two weeks of reinstalling, building etc.) I found a
simple workaround which works in my case.

1. XSLT->process($Doc,null,null,null,true); 

This is to create a copy of the XSLT document in order to replace the
nodes without problems. A case of RTFM. (or in this case, Find A Bug
That Seems Similar, and no there is no acronym for that yet... Any
suggestions?)

2. Replace the call-template in xslt by copy-of.

In XSLT processing I did not need to generate handmade copies of the
element, and now use <xsl:copy-of select="*"/>  in stead of the nice
call-template. This to stay away from some internal XSLT problems. This
problem wasn't solved by the first step though. A case of KISS, nothing
more nothing less. 

If this doesn't help for you, I guess you'll have to start crying
toward the developer of libxslt who most likely will be (partly)
responsible for the mess you are in.


Previous Comments:
------------------------------------------------------------------------

[2004-06-16 21:19:04] rmolier at more-it dot com

The segfault doesn't occur however...

------------------------------------------------------------------------

[2004-06-16 21:16:12] rmolier at more-it dot com

Even more funny:

It seems that only in the case the element was created in the
stylesheet function (which is basically a remove parent element from
list function) the memory leak occurs. Without the XMLInclude this
resulted in one extra free invalid pointer message().

I tested this by adding an additional element to the main document in
the following way:

/* code: begin */

$XMLIncludeElement = $XMLDom->create_element("include");
$XMLIncludedElement = $XMLDom->create_element("gettext");
$XMLIncludedElementText = $XMLDom->create_text_node("Text included in
main document");
$XMLIncludedElement->append_child($XMLIncludedElementText);
$XMLIncludeElement->append_child($XMLIncludedElement);
$XMLDocument->append_child($XMLIncludeElement);

/*code: end */

------------------------------------------------------------------------

[2004-06-16 20:48:26] rmolier at more-it dot com

With option 3 (DOM XML / XInclude /XSLT) I get after the third time:
Allowed memory size of 8388608 bytes exhausted (tried to allocate 10
bytes) and the process dies with 01.

------------------------------------------------------------------------

[2004-06-16 20:37:41] rmolier at more-it dot com

I found a way to reproduce the same behaviour in a simple script. I did
the following tests myself by commenting out some code:

1. DOM + XInclude + XSLT + Replacenode = problem
2. DOM + XInclude + Replacenode = no problem
3. DOM + XInclude + XSLT = no problem
4. DOM + XInclude = no problem
5. DOM + XSLT + Replacenode = no problem
6. DOM + Replacenode = no problem


For the people that would like to reproduce the bug I have created the
following script:

/* xmltest.php: begin */
<?php

echo "Starting Document<br>";

$XMLDom = domxml_new_doc("1.0");

$XMLDocument = $XMLDom->create_element("document");
$XMLDom->append_child($XMLDocument);

$XMLElement = $XMLDom->create_element("replace");
$XMLElementText = $XMLDom->create_text_node("replace this text");
$XMLElement->append_child($XMLElementText);
$XMLDocument->append_child($XMLElement);

$XMLInclude =
$XMLDom->create_element_ns("http://www.w3.org/2001/XInclude","include","xi";);
$XMLInclude->set_attribute("href","include.xml");
$XMLDocument->append_child($XMLInclude);

echo "<pre>";
echo htmlentities($XMLDom->dump_mem(true));
echo "</pre>";

$XMLDom->xinclude();

echo "After Include<br>";
echo "<pre>";
echo htmlentities($XMLDom->dump_mem(true));
echo "</pre>";


$XSLTStylesheet = domxml_xslt_stylesheet_file("stylesheet.xslt");
$XSLTResult = $XSLTStylesheet->process($XMLDom);

echo "After Stylesheet<br>";
echo "<pre>";
echo htmlentities($XSLTResult->dump_mem(true));
echo "</pre>";



$XPathContext =  xpath_new_context($XSLTResult);

$XPathResult = xpath_eval($XPathContext,"//gettext");

echo "<pre>";
print_r($XPathResult);
echo "</pre>";

foreach ($XPathResult->nodeset as $XPathNode)
{
    $XMLParentNode = $XPathNode->parent_node();
    $XMLElementText = $XPathNode->first_child();
    $Text = $XMLElementText->get_content();
    $XMLTextNode = $XSLTResult->create_text_node($Text);
    $XPathNode->replace_node($XMLTextNode);
}

echo "After Replace<br>";
echo "<pre>";
echo htmlentities($XSLTResult->dump_mem(true));
echo "</pre>";
?>

/* xmltest: end */

/* include.xml: begin */

<?xml version="1.0" encoding="UTF-8" ?>
<include>
        <gettext>This is the included replace</gettext>
</include>

/* include.xml: end */

/* stylesheet.xslt */ 

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
        <xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes"/>
        
        <xsl:template match="/">
                <document>
                        <xsl:apply-templates/>
                </document>
        </xsl:template>
        
        <xsl:template match="replace">
                <gettext>
                        <xsl:value-of select="."/>
                </gettext>
        </xsl:template>
        
        
        <xsl:template name="display-element">
                <xsl:element name="{name()}">
                        <xsl:for-each select="@*">
                                <xsl:attribute name="{name()}">
                                        <xsl:value-of select="."/>
                                </xsl:attribute>
                        </xsl:for-each>
                        <xsl:choose>
                                <xsl:when test="count(*) !=0">
                                        <xsl:for-each select="*">
                                                <xsl:call-template 
name="display-element"/>
                                        </xsl:for-each>
                                </xsl:when>
                                <xsl:otherwise>
                                        <xsl:value-of select="."/>
                                </xsl:otherwise>
                        </xsl:choose>
                        
                        
                </xsl:element>  
        </xsl:template>
                
        
        <xsl:template match="include">
                <xsl:for-each select="*">
                        <xsl:call-template name="display-element"/>
                </xsl:for-each>
        </xsl:template>
</xsl:stylesheet>

/* stylesheet.xslt */

------------------------------------------------------------------------

[2004-06-16 19:06:58] rmolier at more-it dot com

To clarify a little on the magical number of 17. It seems, that after
performing the xinclude I perform exactly 17 node replaces on the
included nodes.. 

Think that the problem can be found somewhere there.....

Flow for reproducing:

Create a document from scratch.
Add a number of xinclude statements.
Perform an Xinclude
Perform an XSLT transformation.
Perform an Xpath query on the document.
Replace the resulting nodes with text nodes.

------------------------------------------------------------------------

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/28807

-- 
Edit this bug report at http://bugs.php.net/?id=28807&edit=1

Reply via email to