php – 如何一次处理多个xpath(基于feed结构)或创建具有相同结构
下面的代码经过测试和工作,它会打印具有此结构的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文档时,它再次产生相同的,想要的和正确的结果. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |