XSLT - 将两个不同的XML文件转换为一个,而不重复元素

时间:2013-03-21 22:14:37

标签: php xml xslt transform

我有两个不同的XML文件:movies.xml和Amazon Product Advertising API XML

这是我的XSLT文件,它可以转换两个XML文件:

<?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"
exclude-result-prefixes="aws">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

<xsl:template match="/">
    <xsl:element name="html">
        <xsl:element name="head">
            <xsl:element name="h2">Movies list</xsl:element>
        </xsl:element>
        <xsl:element name="body">
            <xsl:apply-templates select="/movies/movie"/>
            <xsl:apply-templates select="aws:ItemLookupResponse/aws:Items/aws:Item/aws:ItemAttributes/aws:Title"/>
        </xsl:element>
    </xsl:element>
</xsl:template>

<xsl:template match="movie">
    <xsl:element name="a">
        <xsl:attribute name="href">movie_details.php?movieID=<xsl:value-of select="@movieID"/></xsl:attribute>
        <xsl:value-of select="title"/>
    </xsl:element>
    <xsl:element name="br" />
</xsl:template>

<xsl:template match="aws:Title">
    <xsl:element name="h2">Amazon Movie 1</xsl:element>
    <xsl:value-of select="." />
</xsl:template>

</xsl:stylesheet>

apply-templates select =“/ movies / movie - 从movies.xml加载5个电影片段的列表,并将其显示为超链接。

apply-templates select =“aws:ItemLookupResponse / aws:Items / aws:Item / aws:ItemAttributes / aws:Title” - 从Amazon API xml文件加载电影标题并将其显示为纯文本。

这是我的HTML输出:

<html>
  <head>
    <h2>Movies list</h2>
  </head>
  <body>
    <a href="movie_details.php?movieID=1">The Dark Knight Rises</a>
    <br/>
    <a href="movie_details.php?movieID=2">Lawless</a>
    <br/>
    <a href="movie_details.php?movieID=3">Inception</a>
    <br/>
    <a href="movie_details.php?movieID=4">Looper</a>
    <br/>
    <a href="movie_details.php?movieID=5">Django Unchained</a>
    <br/>
  </body>
</html>
<html>
  <head>
    <h2>Movies list</h2>
  </head>
  <body><h2>Amazon Movie 1</h2>Dark Knight Rises [Blu-ray] [2012] [US Import]</body>
</html>

正如您所看到的,这两个模板显示在单独的HTML标记中,这导致两个模板的Head元素“Movies list”显示两次。

如果我能以某种方式将这两个模板放在一个HTML元素中,那么就不会有任何重复。我尝试过几种方法,但还没有成功。

这是我的PHP文件,它创建了两个XML文件和一个XSLT样式表。它还会为亚马逊产品生成一个签名URL。

include('aws_signed_request.php');

$public_key = 'XXXXXXXXXXXXXXXXXXXXXX';
$private_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$associate_tag = 'xxxxxxxxxxxxxxxxxxxxxxx';

// 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
    $xml = new DOMDocument();
    $xml->load('movies.xml');

    $xml2 = new DOMDocument();
    $xml2->loadXML($response);

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

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

    echo $proc->transformToXML($xml);
    echo $proc->transformToXML($xml2);

}

movies.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="index.xsl"?>
<movies
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="movies.xsd">

<movie movieID="1">
    <title>The Dark Knight Rises</title>
</movie>

<movie movieID="2">
    <title>Lawless</title>
</movie>

<movie movieID="3">
    <title>Inception</title>
</movie>

<movie movieID="4">
    <title>Looper</title>
</movie>

<movie movieID="5">
    <title>Django Unchained</title>
</movie>
</movies>

亚马逊产品广告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>

浏览器输出:

browser

2 个答案:

答案 0 :(得分:1)

似乎XSLTProcessor不允许您将XML内容设置为参数(setParameter函数只接受字符串),因此您需要使用XSLT document函数来处理多个输入文档,正如herehere所述。您需要将您的响应从Amazon保存为文件系统中的文件,然后您的XSLT看起来像这样(我已经简化了您的文件名):

<xsl:variable name="amazon" select="document('amazon.xml')"/>

<xsl:template match="/">
    <html>
        <body>
            <h2>Movies List</h2>
            <xsl:apply-templates select="movies/movie" />
            <h2>
                <xsl:value-of select="normalize-space($amazon/aws:ItemLookupResponse/aws:Items/aws:Item/aws:ItemAttributes/aws:Title)"/>
            </h2>
        </body>
    </html>
</xsl:template>

<xsl:template match="movie">
    <a>
        <xsl:attribute name="href">movie_details.php?movieID=<xsl:value-of select="@movieID"/></xsl:attribute>
        <xsl:value-of select="title"/>
    </a>
    <br/>
</xsl:template>

编辑:根据您对原始答案的评论修改代码,并删除有关“多对一”问题的语言。

答案 1 :(得分:1)

我无法重现问题

使用您的XSLT代码(稍微更改为访问&#34; movies.xml&#34;通过调用document()函数):

<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="xml" indent="yes" omit-xml-declaration="yes"/>

<xsl:variable name="vMoviesDoc" select=
 "document('file:///c:/temp/delete/movies.xml')"/>

<xsl:template match="/">
    <xsl:element name="html">
        <xsl:element name="head">
            <xsl:element name="h2">Movies list</xsl:element>
        </xsl:element>
        <xsl:element name="body">
            <xsl:apply-templates select="$vMoviesDoc/movies/movie"/>
            <xsl:apply-templates select="aws:ItemLookupResponse/aws:Items/aws:Item/aws:ItemAttributes/aws:Title"/>
        </xsl:element>
    </xsl:element>
</xsl:template>

<xsl:template match="movie">
    <xsl:element name="a">
        <xsl:attribute name="href">movie_details.php?movieID=<xsl:value-of select="@movieID"/></xsl:attribute>
        <xsl:value-of select="title"/>
    </xsl:element>
    <xsl:element name="br" />
</xsl:template>

<xsl:template match="aws:Title">
    <xsl:element name="h2">Amazon Movie 1</xsl:element>
    <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>

并在本地目录中提供XML文档(文件&#34; movies.xml&#34;)&#34; C:\ temp \ delete&#34;:

<movies xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="movies.xsd">
    <movie movieID="1">
        <title>The Dark Knight Rises</title>
    </movie>
    <movie movieID="2">
        <title>Lawless</title>
    </movie>
    <movie movieID="3">
        <title>Inception</title>
    </movie>
    <movie movieID="4">
        <title>Looper</title>
    </movie>
    <movie movieID="5">
        <title>Django Unchained</title>
    </movie>
</movies>

转换产生以下结果,其中没有重复head

<html>
   <head>
      <h2>Movies list</h2>
   </head>
   <body>
      <a href="movie_details.php?movieID=1">The Dark Knight Rises</a>
      <br/>
      <a href="movie_details.php?movieID=2">Lawless</a>
      <br/>
      <a href="movie_details.php?movieID=3">Inception</a>
      <br/>
      <a href="movie_details.php?movieID=4">Looper</a>
      <br/>
      <a href="movie_details.php?movieID=5">Django Unchained</a>
      <br/>
      <h2>Amazon Movie 1</h2>
            The Dark Knight Rises (Blu-ray/DVD Combo+UltraViolet Digital Copy)
           </body>
</html>