XSLT - 显示位于不同 XML 文件中的子元素

Posted

技术标签:

【中文标题】XSLT - 显示位于不同 XML 文件中的子元素【英文标题】:XSLT - display child elements located in different XML files 【发布时间】:2013-03-22 21:11:14 【问题描述】:

我有以下 movies.xml 文件,用于存储电影标题和用于 dvd 和 Bluray 的 Amazon API ItemId:

<movies
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="movies.xsd">

<movie movieID="1">
    <title>The Dark Knight</title>
    <amazon>
        <dvd>B004Q9SZGC</dvd>
        <bluray>B004Q9T6CO</bluray>
    </amazon>
</movie>

<movie movieID="2">
    <title>Lawless</title>
    <amazon>
        <dvd>B008OPZ83C</dvd>
        <bluray>B008OPZD8C</bluray>
    </amazon>
</movie>

</movies>

movies_list.xsl 将电影标题显示为超链接,将用户带到他们可以看到的movie_details 页面 他们点击的电影标题及其对应的亚马逊 dvd 和蓝光产品信息:

movies_list.xsl

<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: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> 

movie_details.php 从 Amazon API XML 查找并显示电影信息(dvd 和蓝光):

$movies = file_get_contents('movies.xml');
$xml = new SimpleXmlElement($movies);

$movieId = $_GET['movieID'];
$movie = $xml->xpath("/movies/movie[@movieID = '$movieId']")[0];
if($movie) 
   $dvd = $movie->amazon->dvd;
   $bluray = $movie->amazon->bluray;

    $request = aws_signed_request('co.uk', array(
            'Operation' => 'ItemLookup',
            'ItemId' => $dvd.', '.$bluray,
            'ResponseGroup' => 'Medium, Offers',
            'MerchantId' => 'All'), $public_key, $private_key, $associate_tag); 

    $response = @file_get_contents($request);

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

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

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

    $params = $_GET['movieID'];
    $proc->setParameter('', 'movieID', $params);

    echo $proc->transformToXML($xml2);


我没有将实际的 ItemId 值硬编码到数组中,而是创建了 $dvd 和 $bluray 变量 查找存储在本地 movies.xml 文件中的 DVD 和 Bluray 的 ItemId。

这是我的movie_details.xsl 文件,其中显示所有电影详细信息:标题(来自 movies.xml)和亚马逊 DVD 和蓝光图片(来自亚马逊 API):

<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="moviesXML" select="document('movies.xml')"/>

<xsl:param name="movieID"/>

<xsl:template match="/">
    <xsl:element name="html">
        <xsl:element name="head">
            <title>Movie details</title>
        </xsl:element>
        <xsl:element name="body">  
            <xsl:apply-templates select="$moviesXML/movies/movie[@movieID=$movieID]" />
        </xsl:element>
    </xsl:element>
</xsl:template>

<xsl:template match="movie">
        <xsl:value-of select="title"/>
        <xsl:element name="br" />
        <xsl:apply-templates select="../aws:ItemLookupResponse/aws:Items/aws:Item/aws:MediumImage/aws:URL"/>
</xsl:template>

<xsl:template match="aws:URL">
    <xsl:element name="img">
        <xsl:attribute name="src">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:element>
    <xsl:element name="br" />
</xsl:template>

</xsl:stylesheet>

根据用户在movies_list 页面中点击的电影标题,它应该将他带到movie_details 页面 这将显示特定的电影标题及其对应的亚马逊 dvd 和 Bluray URL(链接到产品封面图片),而这些 URL 又将显示为图片。

根据用户在movies_list 页面中单击的电影标题,我确实获得了在movie_details 页面上显示的电影标题。

但是,我不确定我需要放在哪里:

<xsl:apply-templates select="../aws:ItemLookupResponse/aws:Items/aws:Item/aws:MediumImage/aws:URL"/>

同时显示该电影的亚马逊 DVD 和 Bluray 产品信息。

我想要达到的最终结果:

Movie ID 2 应该以相同的方式工作,只是它将显示无法无天的电影信息而不是黑暗骑士。

【问题讨论】:

【参考方案1】:

您可以在这里做的一件事是存储对输入 XML 根目录的引用:

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

然后您可以在第二个模板中执行此操作:

<xsl:template match="movie">
    <xsl:value-of select="title"/>
    <xsl:element name="br" />
    <xsl:apply-templates 
       select="$inputRoot/aws:ItemLookupResponse/aws:Items
                 /aws:Item/aws:MediumImage/aws:URL"/>
</xsl:template>

您似乎还需要修改为您的 Amazon API 请求获取 DVD 和蓝光 ID 的方式:

$movies = file_get_contents('movies.xml');
$xml = new SimpleXmlElement($movies);

$movieId = $_GET['movieID'];
$movieSelect = $xml->xpath("/movies/movie[@movieID = '$movieId']");
$movie = $movieSelect[0];
if($movie) 
   $dvd = $movie->amazon->dvd;
   $bluray = $movie->amazon->bluray;

   // the rest of your code

【讨论】:

感谢您的回复,JLRishe。这种方法对我来说非常有意义,并且它确实部分起作用。无论我点击电影列表页面中的黑暗骑士还是无法无天的片名,movie_details 页面总是显示黑暗骑士亚马逊 DVD 和蓝光图片。因此,例如,如果我单击 Lawless,页面会正确显示标题 Lawless,但 DVD 和蓝光封面仍显示为黑暗骑士,即 movieID 1。这是否与我定义 $dvd 的 PHP 代码和$bluray 变量从 XML 中读取,所以它们只读取第一条记录?谢谢。 所以它看起来总是读取 XML 中的第一个 dvd 和 Bluray ItemId,并为我单击的每个电影标题显示它们。 我认为您需要修改获取 DVD 和 BluRay id 以在 AmazonAPI 请求中使用的方式。请查看我上面添加的 PHP 代码。 感谢您的帮助,JLRishe。我已使用您的解决方案更新了我的代码,但由于某种原因,当我单击任何电影标题时,页面显示“HTTP 错误 500(内部服务器错误)服务器尝试满足请求时遇到了意外情况。”我在原始帖子中更新了我的 PHP 代码。它与我正在使用的 $params 有关吗? 嗯,这很奇怪。您能否删除并重新添加部分以追踪导致问题的行?在设置这两个变量以验证它们是否具有预期值之后,您是否也可以尝试执行echo $dvd . ' ' . $bluray;

以上是关于XSLT - 显示位于不同 XML 文件中的子元素的主要内容,如果未能解决你的问题,请参考以下文章

XML - 使用 XSLT 合并同一节点多次出现的子元素

使用 xslt 获取位于另一个路径中的另一个 xml 值

如果值匹配,XSLT 会更改兄弟元素的子元素值

选择字段元素时不确定 XSLT 文档中的当前路径

在未指定出现顺序时处理 XSLT 中的子标记

XSLT 转换 XML:选择 uuid 并按顺序排序