加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php – 如何一次处理多个xpath(基于feed结构)或创建具有相同结构

发布时间:2020-12-13 17:38:23 所属栏目:PHP教程 来源:网络整理
导读:下面的代码经过测试和工作,它会打印具有此结构的Feed的内容. rss channel item pubDate/ title/ description/ link/ author/ /item /channel/rss 虽然我将xpath更改为/ feed //条目,但我未成功完成的操作是打印遵循此结构的Feed(不同之处在于 feed entry pub
下面的代码经过测试和工作,它会打印具有此结构的Feed的内容.

<rss>
    <channel>
        <item>
            <pubDate/>
            <title/>
            <description/>
            <link/>
            <author/>
        </item>
    </channel>
</rss>

虽然我将xpath更改为/ feed //条目,但我未成功完成的操作是打印遵循此结构的Feed(不同之处在于< feed>< entry>< published>).
你可以在页面源上看到结构.

<feed>
    <entry>
        <published/>
        <title/>
        <description/>
        <link/>
        <author/>
    </entry>
</feed>

我不得不说代码根据pubDate对所有项进行排序.在第二个结构Feed中,我猜它应该根据已发布的条目对所有条目进行排序.

我可能在我找不到的xPath上犯了一个错误.但是,如果在此结束时我设法正确打印该Feed,如何修改代码以同时处理不同的结构?

是否有任何服务允许我根据这些Feed创建和托管我自己的Feed,所以我将拥有相同的结构?我希望我清楚自己……谢谢你.

<?php

$feeds = array();

// Get all feed entries
$entries = array();
foreach ($feeds as $feed) {
    $xml = simplexml_load_file($feed);
    $entries = array_merge($entries,$xml->xpath(''));
}

?>

解决方法

这个答案的主要贡献是一个解决方案(最后),可以使用无限多种格式,只需在外部(全局)参数$postElements和所有“发布日期”替代名称中指定所有“条目”替代名称在外部(全局)参数$pub-dateElements中.

除此之外,这里是如何指定一个XPath表达式,它选择所有/ rss // item和all / feed // entry元素.

在两种可能的文档格式的简单情况下(由@Josh Davis提出)Xpath表达式正确工作:

/rss//item  |   /feed//entry

更通用的XPath表达式允许从一组无限数量的文档格式中选择所需元素:

/*[contains($topElements,concat('|',name(),'|'))]
    //*[contains($postElements,'|'))]

其中变量$topElements应由顶部元素的所有可能名称的竖线分隔的字符串替换,$postElements应由“entry”元素的所有可能名称的竖线分隔的字符串替换.我们还允许“条目”元素在不同文档格式中处于不同深度.

特别是,对于这个具体情况,XPath表达式将是;

/*[contains('|feed|rss|','|'))]
    //*[contains('|item|entry|','|'))]

本文的其余部分展示了如何在XSLT中完全完成所需的处理 – 轻松而优雅.

一,温和的介绍

使用XSLT,这样的处理简单易行:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <myFeed>
   <xsl:apply-templates/>
  </myFeed>
 </xsl:template>

 <xsl:template match="channel|feed">
  <xsl:apply-templates select="*">
   <xsl:sort select="pubDate|published" order="descending"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="item|entry">
  <post>
    <xsl:apply-templates mode="identity"/>
  </post>
 </xsl:template>

 <xsl:template match="pubDate|published" mode="identity">
  <publicationDate>
   <xsl:apply-templates/>
  </publicationDate>
 </xsl:template>

  <xsl:template match="node()|@*" mode="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*" mode="identity"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于此XML文档时(格式为1):

<rss>
    <channel>
        <item>
            <pubDate>2011-06-05</pubDate>
            <title>Title1</title>
            <description>Description1</description>
            <link>Link1</link>
            <author>Author1</author>
        </item>
        <item>
            <pubDate>2011-06-06</pubDate>
            <title>Title2</title>
            <description>Description2</description>
            <link>Link2</link>
            <author>Author2</author>
        </item>
        <item>
            <pubDate>2011-06-07</pubDate>
            <title>Title3</title>
            <description>Description3</description>
            <link>Link3</link>
            <author>Author3</author>
        </item>
    </channel>
</rss>

当它应用于此等效文档时(格式2):

<feed>
        <entry>
            <published>2011-06-05</published>
            <title>Title1</title>
            <description>Description1</description>
            <link>Link1</link>
            <author>Author1</author>
        </entry>
        <entry>
            <published>2011-06-06</published>
            <title>Title2</title>
            <description>Description2</description>
            <link>Link2</link>
            <author>Author2</author>
        </entry>
        <entry>
            <published>2011-06-07</published>
            <title>Title3</title>
            <description>Description3</description>
            <link>Link3</link>
            <author>Author3</author>
        </entry>
</feed>

在两种情况下都需要相同的,产生正确的结果:

<myFeed>
   <post>
      <publicationDate>2011-06-07</publicationDate>
      <title>Title3</title>
      <description>Description3</description>
      <link>Link3</link>
      <author>Author3</author>
   </post>
   <post>
      <publicationDate>2011-06-06</publicationDate>
      <title>Title2</title>
      <description>Description2</description>
      <link>Link2</link>
      <author>Author2</author>
   </post>
   <post>
      <publicationDate>2011-06-05</publicationDate>
      <title>Title1</title>
      <description>Description1</description>
      <link>Link1</link>
      <author>Author1</author>
   </post>
</myFeed>

II.完整的解决方案

这可以推广到参数化解决方案:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="postElements" select=
 "'|entry|item|'"/>
 <xsl:param name="pub-dateElements" select=
  "'|published|pubDate|'"/>

  <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*" mode="identity"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <myFeed>
   <xsl:apply-templates select=
   "//*[contains($postElements,'|'))]">
    <xsl:sort order="descending" select=
     "*[contains($pub-dateElements,'|'))]"/>
   </xsl:apply-templates>
  </myFeed>
 </xsl:template>

 <xsl:template match="*">
  <xsl:choose>
   <xsl:when test=
    "contains($postElements,'|'))">
    <post>
      <xsl:apply-templates/>
    </post>
   </xsl:when>
   <xsl:when test=
   "contains($pub-dateElements,'|'))">
    <publicationDate>
     <xsl:apply-templates/>
    </publicationDate>
   </xsl:when>
   <xsl:otherwise>
    <xsl:call-template name="identity"/>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

</xsl:stylesheet>

此转换可以使用无限多种格式,只需在外部(全局)参数$postElements中指定所有“条目”备用名称,在外部(全局)参数$pub-dateElements中指定所有“已发布日期”备用名称.

任何人都可以尝试这种转换来验证当应用于上面的两个XML文档时,它再次产生相同的,想要的和正确的结果.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读