我正在尝试从AP Webfeed中消化内容,但出于某种原因应该是一个非常简单的for-each循环让我适合。 Feed是来自AP的xml utf-8,使用php xsltprocessor和simplexml。
问题是我无法定位我希望循环的正确节点。 Feed本身是根元素,它具有feed的一些属性,然后是几个“entry”子文章。其中每一个都有条目的子项属性(如版权),然后是实际的nitf含量(铅和身体)
似乎我应该能够<xsl:for-each select="feed/entry" />
但是如果我试图通过名称引用'feed'或'entry',我什么也得不到。我甚至不能做<xsl:value-of select="feed/id" />
- 奇怪的是我可以得到// @ nitf @ version正确返回,但无法通过feed / entry / content / nitf / @ version获得它
我可以通过<xsl:for-each select="//nitf"
&gt;来处理一些内容获取文章正文或nitf节点的任何后代但不是更高的元素(如//条目)。我可以获得更接近root的内容的唯一方法是嵌套<xsl:for-each="/*" />
从根(feed)开始并向下钻取 - 这似乎是错误的。
如果有人能指出我正确的方向,我真的很感激它,令我感到沮丧的是,看起来如此简单的事情让我暂时停留了一段时间。
格式为:
<feed>
<id></id>
<published></published>
<entry>
<copyright></copyright>
<content>
<nitf>
<head></head>
<body></body>
</nitf>
</content>
</entry>
<entry>
<content>
<nitf>
<head></head>
<body></body>
</nitf>
</content>
</entry>
</feed>
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<!-- this does loop through nitf -->
<xsl:for-each select="descendant::*/nitf">
<nitf_title></nitf_title>
</xsl:for-each>
<!-- I want to loop on these instead but this never loops -->
<xsl:for-each select="descendant::*/entry">
<entry_title><entry_title>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
抱歉,我试图保持简短,所以我嘲笑了源码,下面的实际例子
<?xml version="1.0" encoding="utf-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:apcm="http://ap.org/schemas/03/2005/apcm" xmlns:apnm="http://ap.org/schemas/03/2005/apnm" xmlns:georss="http://www.georss.org/georss">
<id>urn:publicid:ap.org:31998</id>
<title type="xhtml">
<apxh:div xmlns:apxh="http://www.w3.org/1999/xhtml">
<apxh:span>AP Online National News</apxh:span>
</apxh:div>
</title>
<apcm:Property Name="FeedProperties">
<apcm:Property Name="Entitlement" Id="urn:publicid:ap.org:product:31998" Value="AP Online National News" />
<apcm:Property Name="FeedSequencing">
<apcm:Property Name="sequenceNumber" Id="111835329" />
<apcm:Property Name="minDateTime" Value="2011-06-20T16:56:08.047Z" />
</apcm:Property>
</apcm:Property>
<updated>2011-06-20T16:56:08.047Z</updated>
<author>
<name>The Associated Press</name>
<uri>http://www.ap.org</uri>
</author>
<rights></rights>
<link rel="self" href="http://syndication.ap.org" />
<entry xmlns="http://www.w3.org/2005/Atom">
<id>urn:publicid:ap.org:badf779c9d5246b5acb21430ed2214fb</id>
<title>APFN-US--Gas Drilling-Chemicals</title>
<updated>2011-06-20T16:56:08.047Z</updated>
<published>2011-06-20T16:25:39Z</published>
<author>
<name>AP</name>
</author>
<rights>Copyright 2011</rights>
<content type="text/xml">
<nitf version="-//IPTC//DTD NITF 3.4//EN" change.date="October 18, 2006" change.time="19:30" xmlns="">
<head>
<docdata>
<doc-id regsrc="AP" />
<date.issue norm="20110620T162539Z" />
<ed-msg info="Eds: APNewsNow." />
<doc.rights owner="http://www.ap.org" agent="http://license.icopyright.net" type="none" />
<doc.copyright holder="AP" year="2011" />
</docdata>
</head>
<body>
<body.head>
<hedline>
<hl1 id="headline">Texas becomes 1st to require fracking disclosure</hl1>
<hl2 id="originalHeadline">Texas becomes 1st to require fracking disclosure</hl2>
</hedline>
<distributor>The Associated Press</distributor>
<dateline>
<location>HOUSTON</location>
</dateline>
</body.head>
<body.content>
<block id="Main">
<p>HOUSTON (AP) — Texas </p>
</block>
</body.content>
<body.end />
</body>
</nitf>
</content>
<apcm:ContentMetadata xmlns:apcm="http://ap.org/schemas/03/2005/apcm">
<apcm:DateLineLocation City="Houston" Country="USA" CountryArea="TX" CountryAreaName="Texas" CountryName="United States" />
<apcm:Priority Numeric="4" Legacy="r" />
<apcm:ConsumerReady>TRUE</apcm:ConsumerReady>
<apcm:DateLine>HOUSTON</apcm:DateLine>
</apcm:ContentMetadata>
</entry>
<entry xmlns="http://www.w3.org/2005/Atom">
<id>urn:publicid:ap.org:57582781c3a841a2b9849231a4abdb63</id>
<title>US--Medicare-Prevention</title>
<updated>2011-06-20T16:54:57.963Z</updated>
<published>2011-06-20T16:54:43Z</published>
...
答案 0 :(得分:2)
正如上面的评论中所指出的,您的问题与源文档中的命名空间有关。例如,您尝试匹配名为“entry”的元素,但实际元素的限定名称为{http://www.w3.org/2005/Atom}:entry。
您应该使用前缀重写xpath以包含命名空间限定符,然后将该前缀映射到适当的值。结果,“entry”变为“atom:entry”,一些封闭元素的原子声明为xmlns:atom =“http://www.w3.org/2005/Atom”。
答案 1 :(得分:2)
与上面的注释不同,您实际上不需要任何名称空间声明来选择nitf
元素,作为无名称空间(xmlns=""
)中的元素。实际上,您只需使用nitf
即可在文档中选择任何//
元素。例如:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of select="//nitf"/>
</xsl:template>
</xsl:stylesheet>
将输出类型为nitf
的所有节点的所有节点,无论父节点派生的名称空间如何。
不同的命名空间改为entry
,即xmlns="http://www.w3.org/2005/Atom"
。要正确选择此元素,您必须在文档中声明名称空间前缀,并相应地使用它。例如:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:atom="http://www.w3.org/2005/Atom">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select="//nitf">
<!-- iterate on nitf children -->
</xsl:for-each>
<xsl:for-each select="//atom:entry">
<!-- iterate on entry children -->
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
首先会对所有{}:nitf
的子项进行迭代,然后对任何{http://www.w3.org/2005/Atom}:entry
的子进行迭代。
为什么您的第一个XPath无法正常工作
在第一个XPath中:
descendant::*/nitf
您正在使用轴来选择任何nitf
。使用*
强制XPath选择所有nitf
元素, null 命名空间中元素的后代。但是,您没有null命名空间的nitf
元素后代。 nitf
是http://www.w3.org/2005/Atom
命名空间uri中的元素的子元素。
这里使用轴的正确方法是,在声明了http://www.w3.org/2005/Atom
的名称空间前缀之后(如前面的示例所示):
descendant::atom:*/nitf
或者,您也可以使用低级别:
descendant::node()/nitf
最后,最简单的方法是(如上面的第一个例子所示):
//nitf
请注意,最后两个XPath将选择任何名称空间中限定的元素后代的nitf
个元素。因此,当您完全了解输入文档并且知道自己在做什么时,应该使用它们。