2

I hope someone can help me I am stuck at this for a while..

i am an affiliate and i get xml data from the provided. I am trying to convert this data and display as html on my site.

I have tested my xsl and can confirm that the xsl is displaying the data as i wanted.

My issue is that the php code to extract the data from urla and trasform the data using xsl to display html is not working.

<?php


    $context = stream_context_create(array('http' => array('header' => 'Accept: application/xml')));

    $url = 'http://merchandising.expediaaffiliate.com/campaign/?campaignId=85413&cid=409870 ';

    $xml = file_get_contents($url, false, $context);

    $xml = simplexml_load_string($xml);

    $doc = new DOMDocument();

    $doc->load('http://sitename/hotels.xslt');

    $xsl = new XSLTProcessor();

    $xsl->importStyleSheet($doc);

    $doc->load($xml);

    echo $xsl->transformToXML($doc);


    ?>

My XSl is below:

<?xml version="1.0" encoding="ISO-8859-1"?>

<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">

     <xsl:for-each select="HotelAvailabilityListResults">
    <xsl:for-each select="Hotel">


      <div style="background-color:teal;color:white;padding:4px">
        <span style="font-weight:bold"><xsl:value-of 
    select="name" 
    disable-output-escaping="yes"/></span>
        - <xsl:value-of select="city"/>
      </div>
      <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
        <p><xsl:value-of select="shortDescription" 
    disable-output-escaping="yes"/>.
        <span style="font-style:italic">
          <xsl:value-of select="address1" 
    disable-output-escaping="yes"/>
        </span>.</p>
 <p>
        <span style="font-style:italic">
       <xsl:element name="img">
    <xsl:attribute name="src">

    <xsl:value-of select="thumbNailUrl"/>
    </xsl:attribute>
    </xsl:element>
        </span>.</p>
      </div>
<span style="font-style:italic">
          <xsl:value-of select="HotelProperty/promoDescription"  />
        </span>
<span style="font-style:italic">
          <xsl:value-of select="ValueAdds/ValueAdd"  />
        </span>
<div>
 <span style="font-style:italic">
       <xsl:element name="a">
    <xsl:attribute name="href">

    <xsl:value-of select="hotelUrl"/>
    </xsl:attribute>
    </xsl:element>
        </span>
</div>
    </xsl:for-each>
    </xsl:for-each>



  </body>
</html>
Jai
  • 97
  • 2
  • 14

1 Answers1

0

You have two problems, first the XML is bad, the descriptions are not CDATA sections, but text nodes. Looks like somebody escaped it two times. To use them in XSLT you need to repair them.

$context = stream_context_create(array('http' => array('header' => 'Accept: application/xml')));
$url = 'http://merchandising.expediaaffiliate.com/campaign/?campaignId=85413&cid=409870 ';
$xml = file_get_contents($url, false, $context);

$xmlDom = new DOMDocument();
$xmlDom->loadXml($xml);

$xpath = new DOMXPath($xmlDom);

/* repair double escaped cdatas */
$translationTable = array_flip(
  get_html_translation_table(HTML_ENTITIES, ENT_QUOTES | ENT_HTML5, 'UTF-8')
);
$nodes = $xpath->evaluate('//text()[starts-with(., "<![CDATA[")]');  
foreach ($nodes as $node) {
  $fragment = $xmlDom->createCDATASection(
    str_replace(
      array_keys($translationTable),
      $translationTable,
      substr($node->nodeValue, 9, -3)
    )
  );
  $node->parentNode->appendChild($fragment);
  $node->parentNode->removeChild($node);
}

$xslDom = new DOMDocument();
$xslDom->load('template.xsl');

$xsl = new XSLTProcessor();
$xsl->importStyleSheet($xslDom);

echo $xsl->transformToXML($xmlDom);

The template in your question is not a XSLT stylesheet. The root element of an XSLT is stylesheet. You need to match something from the XML, too.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output 
    method="html"
    encoding="UTF-8" 
    standalone="yes"
    indent="yes"/>

  <xsl:template match="/">
    <html >
      <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
        <xsl:for-each select="HotelAvailabilityListResults">
          <xsl:for-each select="Hotel">
            <div style="background-color:teal;color:white;padding:4px">
              <span style="font-weight:bold">
                <xsl:value-of select="name"/>
              </span>
              - <xsl:value-of select="city"/>
            </div>
            <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
              <p>
                <xsl:value-of select="shortDescription" disable-output-escaping="yes"/>.
                <span style="font-style:italic">
                  <xsl:value-of select="address1"/>
                </span>
              </p>
              <p>
                <span style="font-style:italic">
                  <img src="{thumbNailUrl}"/>
                </span>.
              </p>
            </div>
            <span style="font-style:italic">
              <xsl:value-of select="HotelProperty/promoDescription"/>
            </span>
            <span style="font-style:italic">
              <xsl:value-of select="ValueAdds/ValueAdd"  />
            </span>
            <div>
              <span style="font-style:italic">
                <a href="{hotelUrl}">
                  <xsl:value-of select="hotelUrl"/>
                </a>
              </span>
            </div>
          </xsl:for-each>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

Some additional hints for your XSLT:

  1. Be careful with disable-out-escaping="yes", this opens you up to HTML injections. You have to trust the source. Avoid it if possible.
  2. You can use {} inside attribute values to access Xpath, removes a lot of clutter from <xsl:element/> and <xsl:attribute/>
ThW
  • 19,120
  • 3
  • 22
  • 44