将 XSLT 样式表应用于亚马逊产品广告 API XML 输出
Posted
技术标签:
【中文标题】将 XSLT 样式表应用于亚马逊产品广告 API XML 输出【英文标题】:Apply XSLT stylesheet to Amazon Product Advertising API XML output 【发布时间】:2013-03-11 03:13:46 【问题描述】:我正在尝试将我的 XSLT 样式表应用于 Amazon API xml 输出并在页面上显示电影标题
这是我的 XSLT 文件 (amazon.xsl):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:aws="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
<xsl:output method="xml" version="1.0" omit-xml-declaration="yes" indent="yes" media-type="text/html"/>
<xsl:template match="/">
<xml>
<root>
<xsl:apply-templates select="aws:ItemLookupResponse/aws:Items/aws:Item/aws:ItemAttributes/aws:Title" />
</root>
</xml>
</xsl:template>
<xsl:template match="aws:Title">
<xsl:text>Movie title</xsl:text>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
这是亚马逊 API XML 输出:
<ItemLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
<OperationRequest>
<HTTPHeaders>
<Header Name="UserAgent" Value="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22"/>
</HTTPHeaders>
<RequestId>a1138e89-4335-4650-80f2-641e3c58b623</RequestId>
<Arguments>
<Argument Name="Operation" Value="ItemLookup"/>
<Argument Name="Service" Value="AWSECommerceService"/>
<Argument Name="Signature" Value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/>
<Argument Name="AssociateTag" Value="xxxxxxxxxxxxxx"/>
<Argument Name="Version" Value="2011-08-01"/>
<Argument Name="ItemId" Value="B004LWZWGK"/>
<Argument Name="AWSAccessKeyId" Value="xxxxxxxxxxxxxxxxxxxx"/>
<Argument Name="Timestamp" Value="2013-03-21T13:56:55.000Z"/>
<Argument Name="ResponseGroup" Value="Small"/>
</Arguments>
<RequestProcessingTime>0.0189320000000000</RequestProcessingTime>
</OperationRequest>
<Items>
<Item>
<ItemAttributes>
<Title>
The Dark Knight Rises (Blu-ray/DVD Combo+UltraViolet Digital Copy)
</Title>
</ItemAttributes>
</Item>
</Items>
</ItemLookupResponse>
我找到并使用了以下 php 代码来搜索电影标题并将其显示在页面上。然而,它 仅以纯文本形式显示。我想对其应用 XSLT 样式,但我不知道如何正确地将其包含在我的 php 代码中。
如果正确使用 XSLT,它将在实际标题上方显示“电影标题”。
amazon.php
include('aws_signed_request.php');
$public_key = 'XXXXXXXXXXXXXXXXXXXX';
$private_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$associate_tag = 'xxxxxxxxxxxxxxxxxxxxxxxxx';
// generate signed URL
$request = aws_signed_request('co.uk', array(
'Operation' => 'ItemLookup',
'ItemId' => 'B004LWZWGK',
'ResponseGroup' => 'Small'), $public_key, $private_key, $associate_tag);
// do request (you could also use curl etc.)
$response = @file_get_contents($request);
if ($response === FALSE)
echo "Request failed.\n";
else
// parse XML
$xsl = new DOMDocument;
$xsl->load('amazon.xsl');
$proc = new XSLTProcessor();
$proc->importStyleSheet($xsl);
$doc = DOMDocument::loadXML($response);
$transform = $proc->transformToXML($doc);
$pxml = simplexml_load_string($transform);
if ($pxml === FALSE)
echo "Response could not be parsed.\n";
else
if (isset($pxml->Items->Item->ItemAttributes->Title))
echo $pxml->Items->Item->ItemAttributes->Title, "\n";
*aws_signed_request.php*
function aws_signed_request($region, $params, $public_key, $private_key, $associate_tag=NULL, $version='2011-08-01')
/*
Parameters:
$region - the Amazon(r) region (ca,com,co.uk,de,fr,co.jp)
$params - an array of parameters, eg. array("Operation"=>"ItemLookup",
"ItemId"=>"B000X9FLKM", "ResponseGroup"=>"Small")
$public_key - your "Access Key ID"
$private_key - your "Secret Access Key"
$version (optional)
*/
// some paramters
$method = 'GET';
$host = 'webservices.amazon.'.$region;
$uri = '/onca/xml';
// additional parameters
$params['Service'] = 'AWSECommerceService';
$params['AWSAccessKeyId'] = $public_key;
// GMT timestamp
$params['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
// API version
$params['Version'] = $version;
if ($associate_tag !== NULL)
$params['AssociateTag'] = $associate_tag;
// sort the parameters
ksort($params);
// create the canonicalized query
$canonicalized_query = array();
foreach ($params as $param=>$value)
$param = str_replace('%7E', '~', rawurlencode($param));
$value = str_replace('%7E', '~', rawurlencode($value));
$canonicalized_query[] = $param.'='.$value;
$canonicalized_query = implode('&', $canonicalized_query);
// create the string to sign
$string_to_sign = $method."\n".$host."\n".$uri."\n".$canonicalized_query;
// calculate HMAC with SHA256 and base64-encoding
$signature = base64_encode(hash_hmac('sha256', $string_to_sign, $private_key, TRUE));
// encode the signature for the request
$signature = str_replace('%7E', '~', rawurlencode($signature));
// create request
$request = 'http://'.$host.$uri.'?'.$canonicalized_query.'&Signature='.$signature;
return $request;
我知道这是很多代码,但是 PHP 中的所有内容都运行良好,并且我确实在页面上显示了电影标题。我只想将我的 XSLT 样式表也应用到它。我对 PHP 很陌生,不知道如何正确地做到这一点。
【问题讨论】:
如果要转换 XML 并在浏览器中显示,则需要将其转换为 HTML。浏览器不知道如何处理<xml><root></root></xml>
(并且xml
也不是合法的元素名称)。
感谢您的回复,JLRishe。但是我会用什么来代替 要回答 cmets 的问题,您可以通过以下方式从该输入生成 HTML 页面:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:aws="http://webservices.amazon.com/AWSECommerceService/2011-08-01"
exclude-result-prefixes="aws">
<xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/">
<html>
<head>
<title></title>
</head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="aws:Title">
<h1>
<xsl:text>Movie Title</xsl:text>
</h1>
<xsl:value-of select="." />
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
在您的示例输入上运行时,会产生:
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title></title>
</head>
<body>
<h1>Movie Title</h1>
The Dark Knight Rises (Blu-ray/DVD Combo+UltraViolet Digital Copy)
</body>
</html>
如果您只想生成一个 HTML 片段以添加到您正在显示的较大页面中,您可以使用这个:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:aws="http://webservices.amazon.com/AWSECommerceService/2011-08-01"
exclude-result-prefixes="aws">
<xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="aws:Title">
<div>
<h1>
<xsl:text>Movie Title</xsl:text>
</h1>
<xsl:value-of select="." />
</div>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
产生:
<h1>Movie Title</h1>
The Dark Knight Rises (Blu-ray/DVD Combo+UltraViolet Digital Copy)
【讨论】:
我使用了您提供的第二种解决方案,JLRishe。我在 php 页面上收到以下两个警告:1)“警告:simplexml_load_string():实体:第 1 行:解析器错误:第 35 行 myservername/amazon.php 中文档末尾的额外内容警告:simplexml_load_string() :” 2) “警告:simplexml_load_string(): ^ in myservername/amazon.php on line 35 响应无法解析。”我确实得到了“电影标题”和页面上显示的实际标题,但我也得到了这些警告。有任何想法吗?谢谢你的帮助。 这可能是因为结果没有单个根元素。我不认为真的需要在结果上使用simplexml_load_string()
,但如果你愿意,我认为我刚刚在上面所做的修改,将内容包装在div
中,应该可以解决该警告。
JLRishe,警告已经完全消失,但现在页面完全空白,根本不显示任何内容。它是否与 Chris 之前提供的“transformToXML”解决方案有关?我已经用他的解决方案更新了我的 amazon.php,所以那里可能缺少一些东西?再次感谢您的帮助!
这一行之后:$transform = $proc->transformToXML($doc);
请尝试echo $transform;
。我不认为那行之后的东西是必要的。
是的!现在一切正常。你不知道我努力让这个亚马逊 api 正常工作多久了。 JLRiche,非常感谢您的帮助!【参考方案2】:
您已创建处理器并在amazon.php
的第 6 行和第 7 行导入样式表,但您仍需要使用 XSLTProcessor::transformToXML
应用它
// parse XML
$doc = DOMDocument::loadXML($response);
$transform = $proc->transformToXML($doc);
$pxml = simplexml_load_string($transform);
【讨论】:
感谢您的回复,克里斯。我已经使用了您的解决方案,但现在页面根本不显示任何内容。我已经更新了上面的 amazon.php 代码。所以也许你可以看看它并指出我犯的一个错误。我对 php 很陌生。谢谢以上是关于将 XSLT 样式表应用于亚马逊产品广告 API XML 输出的主要内容,如果未能解决你的问题,请参考以下文章
亚马逊产品广告 API 的 TooManyRequestsException