Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XSLTProcessor doing something bad

Status
Not open for further replies.

tlhawkins

Programmer
Dec 28, 2000
797
0
0
US
Hey,

I don't use PHP for XML a lot but I have a project where I need to do a lot of XSLT transformations. The first one I setup worked great.

The second one... not so much.

Here is what is happening, picture this:

XML:
Code:
<data>
  <customer>
    <name>My Name</name>
    <address>My Address</name>
    <phone>5055550505</phone>
  </customer>
</data>
XSL:
Code:
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="1.0">
<xsl:template match="/">
<xsl:apply-templates select="Data/Customer"/></xsl:template>
<xsl:template match="/Customer">
  <Format>
    <BuildThis>
       <xsl:value-of select="name"/> - <xsl:value-of select="phone"/>
    </BuildThis>
  </Format>
</xsl:template>
</xsl:stylesheet>

Now, the output is this:
Code:
          My Name 
          My Address 
          5055550505

That's right... it is outputing the original XML, with formatting still in place, but no tags.

What in the world could cause something like this?
Thanks



Travis Hawkins
 
This is the code I use for my Transformation:

Code:
function transformXML($xmlFile, $xslFile)
{
  try {
    $xslDoc = new DOMDocument('1.0', 'UTF-8');
    $xslDoc->load($xslFile);
    $xmlDoc = new DOMDocument('1.0', 'UTF-8');
    if (!$xmlDoc->load($xmlFile)) {
	  echo 'XML load Failed: <br/>';
	  print_r(error_get_last());
    }
    $proc = new XSLTProcessor();
    $proc->importStylesheet($xslDoc);
    $result = $proc->transformToXML($xmlDoc);
  } catch (Exception $ex) {
    throw new apException("Unable to transform XSL");
  }
  return $result;
}

There is no Exception thrown, but the transformation is all wacky.

Travis Hawkins
 
your data xml is tag mismatched on the address line. this is causing the DOMDocument to fail in loading.

additionally your stylesheet addresses the data and customer tags as Data and Customer. transform to lowercase and all will be well.
 
Thanks for taking a look, I apologize for all the type-errors, my XML is actually correct, or, as you can see from the code it would output an error if the DOMDOC wouldn't load.

the freaky thing is that no matter what the XSL says to output it's outputing the XML DATA without the tags.

For instance the XML:
Code:
<data>
  <customer>
    <name>My Name</name>
    <address>My Address</address>
    <phone>5055550505</phone>
    <biscuits>yes please</biscuits>
  </customer>
</data>
With the XSL:
Code:
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="1.0">
<xsl:template match="/">
<xsl:apply-templates select="data/customer"/></xsl:template>
<xsl:template match="/customer">
  <Format>
    <BuildThis>
       <xsl:value-of select="name"/> - <xsl:value-of select="phone"/>
    </BuildThis>
  </Format>
</xsl:template>
</xsl:stylesheet>
will output

My Name
My Address
5055550505
yes please

it's like it's just filtering out the XML tags and leaving the data. I don't think I could write XSL to do that if that's what I wanted... but it definitely ISN'T what I want.

can you, or anyone else, think of any reason why it would be just outputing the data of the XML.

another goofy thing... if I mess with the XSL a little, sometimes i can get it to output the XML FROM the XSL, but without the data from the XML. Like this XSL:

Code:
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="1.0">
<xsl:template match="/data">
<xsl:apply-templates select="customer"/></xsl:template>
<xsl:template match="customer">
  <Format>
    <BuildThis>
       <xsl:value-of select="name"/> - <xsl:value-of select="phone"/>
    </BuildThis>
  </Format>
</xsl:template>
</xsl:stylesheet>
will output:
<Format><BuildThis/></Format>

just like that, no carriage returns, or even a blank value for the <BuildThis> tag.

Driving me crazy

Travis Hawkins
 
><xsl:template match="/customer">
What do you think it means?
[tt]<xsl:template match="[highlight]c[/highlight]ustomer">[/tt]
 
using your code as was, i DID receive an error when the DOMdoc did not load. when i corrected the tag mismatch and the match type sensitivity no errors were received and the code outputted just fine. it is of concern that you do not have the same behaviour.

from the latest code you posted I receive this as source output:

Code:
<?xml version="1.0"?>
<Format><BuildThis>My Name - 5055550505</BuildThis></Format>

this is exactly what i would expect.

if I add this into the stylesheet
Code:
<xsl:output method="html" encoding="iso-8859-1" indent="no"/>

the output is then like so
Code:
<Format><BuildThis>My Name - 5055550505</BuildThis></Format>
(no xml tag)

again, exactly what I would expect
 
Well, I reinstalled my php_xsl.dll and it fixed it. Not sure if I had an old version of that dll, or if it had gotten corrupted somehow. Thanks for helping me be sure I wasn't jusr crazy :)

Travis Hawkins
 
To the vacuum:
If that "/customer" works "as expected", you can file a bug report to php. That's ridiculous.
 
I was wondering what you were saying there tsuji, I read it over a few times and didn't know what your point was. "/customer" should pull from the root node right?
whereas "customer" can match anywhere (or nearly so).

I think it wasn't actually matching, in fact, it didn't look like it was actually transforming anything, it was just passing the XML through without tags. The XSL never affected the output until I reinstalled it. It was a "Bug" but I think it was more a localized thing on my server rather than something PHP did wrong.

Travis Hawkins
 
[1] This line:
><xsl:template match="/customer">
makes the template matching customer node directly under root document, the position now occupied by <data> node. So that template with <Format><BuildThis> production never gets a chance to be called.

[2] This:
[tt]<xsl:template match="customer">[/tt]
will match customer when it is traversed. How come it is traversed? It is because of this instruction:
[tt]<xsl:apply-templates select="data/customer"/></xsl:template>[/tt]

[3] How comes you got that text without Format and BuildThis tags? It is because all xslt processor implements default template matching text nodes. If you got those outputted, it proves that xslt processor is in action, before so-said "reinstalled".

[4] If you add this template to suppress the default template's action:
[tt]<xsl:template match="text()" />[/tt]
you won't see any output in your xsl document, and that proves as well the template matching "/customer" is never called upon.
 
>but glad to know there was a reason
Well, if that does not light up, that means you are not ready.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top