您的位置:首页 > 产品设计 > UI/UE

使用 XQuery 聚合 RSS 和 Atom 信息

2020-02-16 22:50 639 查看
在将过滤指令嵌入到用来生成输出格式的文档中后,XQuery 可以使合并和过滤 XML 文档中的信息变得更容易。您可以使用该功能将来自 RSS 和 Atom 提要的信息聚合成您需要的格式。本文将查看 RSS 和 Atom 格式的结构,并了解 XQuery 如何能够简化这类信息的显示。

RSS 和 Atom 的基础知识

Really Simple Syndication (RSS) 和 Atom 标准提供了针对各种不同使用的项的 XML 结构。最常见的 RSS 和 Atom 提要应用是数据分发格式,用于改进 Weblogs 和新闻站点。

RSS 和 Atom 提要包含相对较少的信息。因此,很容易下载文件,减少 Web 服务器的负载,而不是在用户查看整个博客帖子页面时提供通常很分散的所有信息。此外,RSS 和 Atom 文件还包含更多详细的排序信息,比如作者、标题、主题和密码标记信息,这些信息用于帮助识别和组织提要中的数据。

.rss详细例子 

<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.0.4" -->
<rss version="2.0"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  >

<channel>
  <title>MCslp</title>
  <link>http://mcslp.com</link>
  <description>News from the desk of Martin MC Brown</description>
  <pubDate>Wed, 07 Nov 2007 23:25:53 +0000</pubDate>
  <generator>http://wordpress.org/?v=2.0.4</generator>
  <language>en</language>
      <item>
    <title>System Administration Toolkit: Testing system validity</title>
    <link>http://mcslp.com/?p=269</link>
    <comments>http://mcslp.com/?p=269#comments</comments>
    <pubDate>Wed, 07 Nov 2007 23:25:48 +0000</pubDate>
    <dc:creator>Martin MC Brown</dc:creator>
   
  <category>Articles</category>
  <category>IBM developerWorks</category>
  <category>Open Source</category>
  <category>System Administration</category>
    <guid isPermaLink="false">http://mcslp.com/?p=269</guid>
    <description><![CDATA[Have you ever wondered whether the system you are
using is the same as the one that you originally configured?
Making sure that the configuration and setting information that you configured is the
same as when you configured it should be a basic part of any security procedure.
After all, if an unscrupulous person has [...]]]></description>
      <content:encoded><![CDATA[<p>Have you ever wondered whether the
  system you are using is the same as the one that you originally configured?
  </p>
<p>Making sure that the configuration and setting information that you configured
is the same as when you configured it should be a basic part of any security procedure.
After all, if an unscrupulous person has changed the configuration of your system, you
want to know about it. </p>
<p>Tracking that information though can be difficult. You can't expect to
check the contents of every single file. Even if you automated the process, the
potential quantity of information to be checked could be enormous and often what you
want first is a quick indication of where to start looking. </p>
<p>In my new article, System Administration Toolkit: Testing system validity I
show you a number of techniques forrecording and verifying this information, and
include sample scripts that will automate the process foryou. </p>
<p>Read: <a href="http://www.ibm.com/developerworks/aix/library/
au-satsystemvalidity/index.html?ca=drs-">Systems Administration Toolkit:
Testing system validity</a>
</p>
]]></content:encoded>
      <wfw:commentRSS>http://mcslp.com/?feed=rss2&p=269</wfw:commentRSS>
    </item>
...
</rss>

 

清单 2 中是 Atom 格式的相同信息。

<?xml version="1.0" encoding="UTF-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
  <title>MCslp</title>
  <link rel="alternate" type="text/html" href="http://mcslp.com"/>
  <tagline>News from the desk of Martin MC Brown</tagline>
  <modified>2007-11-07T23:25:53Z</modified>
  <copyright>Copyright 2007</copyright>
  <generator url="http://wordpress.org/"
           version="2.0.4">WordPress</generator>
  <entry>
    <author>
      <name>Martin MC Brown</name>
    </author>
    <title type="text/html" mode="escaped"
      ><![CDATA[System Administration Toolkit:
           Testing system validity]]></title>
    <link rel="alternate" type="text/html" href="http://mcslp.com/?p=269"/>
    <id>http://mcslp.com/?p=269</id>
    <modified>2007-11-07T23:25:48Z</modified>
    <issued>2007-11-07T23:25:48Z</issued>

    <dc:subject>Articles</dc:subject>
    <dc:subject>IBM developerWorks</dc:subject>
    <dc:subject>Open Source</dc:subject>
    <dc:subject>System Administration</dc:subject>
    <summary type="text/plain" mode="escaped"><![CDATA[Have you ever
wondered whether the system you are using is the same as the one that you
originally configured?
Making sure that the configuration and setting information that you configured
is the same as when you configured it should be a basic part of any security
procedure. After all, if an unscrupulous person has [...]]]></summary>
    <content type="text/html" mode="escaped"
          xml:base="http://mcslp.com/?p=269"><![CDATA[...]]></content>
  </entry>

 

表 1 是可从 RSS 和 Atom 文件中提取的信息摘要。此表列出了每种类型的信息的对应 XML 标记。稍后需要使用此表解析和处理这些独特的文件。


表 1. 可从 RSS 和 Atom 文件中提取的信息摘要

RSS Atom 描述
通道 提要 提要信息的根源
标题 标题 提要的标题,或者帖子的标题
链接 链接 到原始主机的链接,或者到单个帖子的链接
条目 单个新闻项或博客帖子的根源
dc:creator 作者 帖子的作者
发布日期 修改日期 修改日期
发布日期 发出日期 发布日期
种类 dc:subject 种类或主题
描述 摘要 帖子的摘要
content:encoded 内容 完整的帖子内容

通常可以解析组成提要信息的 XML 文件的内容,然后用合适的格式打印出该信息。

传统 RSS 和 Atom 处理

在查看 XQuery 解决方案之前,将了解更传统的解决方案如何处理 RSS 和 Atom 文件解析以及生成输出过程中出现的问题。进行此演示的目的是为了让您了解如何将 RSS 和 Atom 提要转换成 HTML。

处理 RSS 或 Atom 提要的传统方法是使用编程语言(比如 Perl、PHP 或 Java)并解析整个 XML 文件内容。然后动态输出该信息,或者将该信息输出成静态 HTML 文件来显示它。

在清单 3 中可以看到一个 Perl 处理器样例。该脚本使用

XML::FeedPP
模块,此模块可为您处理许多复杂事物。该模块下载并解析 XML,以可迭代对象形式返回信息,以便输出项标题和链接地址。


清单 3. 使用

XML::FeedPP
模块的基于 Perl 的解析器

use XML::FeedPP;

my $source = 'http://planet.mcslp.com/wp-rss2.php';

my $feed = XML::FeedPP->new( $source );

print <<EOF;
<html>
<body>
<b>All the news that's fit to print</b>
<hr/>
EOF

foreach my $item ($feed->get_item())
{
my ($title,$link) = ($item->link(),$item->title());

print <<EOF;
<div>
RSS item <b>$title</b> is located at <b>$link</b>
</div>
EOF

}

print <<EOF
</body>
</html>
EOF

运行脚本就可以得到类似清单 4 中所示的输出。该输出是 HTML 格式的,当然,使用编程语言解决方案的好处是可以将信息插入数据库。


清单 4. 从基于 Perl 的 RSS 解析器中截取的输出

<html>
<body>
<b>All the news that's fit to print</b>
<hr/>
<div>
RSS item <b>http://feeds.computerworld.com/~r/Computerworld/MartinMCBrown/
~3/188475547/six_months_with_two_skype_phones</b> is located at <b>Six
months with two Skype phones</b>
</div>
<div>
RSS item <b>http://feeds.computerworld.com/~r/Computerworld/MartinMCBrown/
~3/187849420/what_to_do_with_the_old_computing_bits_and_pieces</b> is located
at <b>What to do with the old computing bits and pieces</b>
</div>
...
</div>
</body>
</html>

使用编程解决方案的一个问题是处理 XML 是一个相对复杂的过程,不同的实现和语言对于 XML 信息处理有着不同的处理能力级别。

但是,最复杂的情况(尤其对大多数语言而言)是标记和编程元素常常组合在相同文件中,这使得实际的处理可能非常复杂。修改输出样式和 20000 布局可能很困难,甚至难以解决,因为这可能需要对编程逻辑进行显著更改才能得以实现。

另一个可供选择的办法是使用 XSLT 样式表,将信息动态转换成 HTML。清单 5 中显示了一个 XSLT 示例,该 XSLT 生成了与 Perl 脚本提供的输出相同的基本输出。


清单 5. 使用 XSLT 样式表

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="rss/channel">
<html>
<body>
<xsl:apply-templates select="item" />
</body>
</html>
</xsl:template>
<xsl:template match="item">
<div>
RSS item <b><xsl:value-of select="title"/></b> is located
at <b><xsl:value-of select="link"/></b>
</div>
</xsl:template>
</xsl:stylesheet>

XSLT 解决方案具有的主要优点是可以将处理的编程部分作为格式的源嵌入相同文件。您可以看到基本的文档结构,甚至可以添加解析单个组件的 XSL 语句。

使用 XSLT 的不利方面是输入 XML 的复杂性和输出文件的复杂性可能导致更复杂的处理。尽管 XSLT 支持基本编程概念(比如循环),甚至支持一些更复杂的数据和信息处理,但与完整的编程语言比较,它的能力是非常有限的。这种复杂性可能导致处理较慢,尤其是特别大和复杂的文件。

如果亲自实践,您就会发现编写一个同时处理所有 RSS 和 Atom 提要元素的 XSL 转换会很难,但也不是不可能。理解输出以及其工作方式可能非常困难。



回页首[/td]

[tr][td]
[/tr]

使用 XQuery 动态转换 RSS

XQuery 将 XPath 规范语言提取单个元素的灵活性与易于定义函数、循环和可编程元素的能力结合在一起。这种结合将 XPath 中简化的路径处理转换成一种在处理期间读取和处理信息的更灵活方式。

与 XSLT 不同,XQuery 拥有用户更熟悉的编程环境和执行模型,并且有一些令信息处理更容易的强大排序,从而不必求助基于编程语言的解决方案。

让我们从一个非常简单的、等同于前面示例的例子开始吧,该示例以基本 HTML 文件(清单 6)的形式输出 RSS 源中的信息。


清单 6. 一个简单的基于 XQuery 的 RSS 解析器

declare function local:rss-row ($link, $title)
{
<div>
RSS item <b>{$title}</b> is located at <b>{$link}</b>
</div>
};

declare function local:rss-summary ($url)
{
for$b in doc($url)/rss/channel/item
return local:rss-row($b/link/text(), $b/title/text())
};

<html>
<body>
<b>All the news that's fit to print</b>
<hr/>

{local:rss-summary("planet.rss2.xml")}

</body>
</html>

可以按如下所示分析查询:

  1. 主要组成部分是 <html> 标记中的部分,这部分包括一个对本地 rss-summary 函数的调用,该函数提供 RSS 源(在这里是一个本地文件,尽管它可能是一个 URL)。
  2. 通过使用 XPath 规范,前面声明的 rss-summary 函数使用了一个 for循环在每个项上进行迭代,以便选择每个项。
  3. 要获得每个项,可调用本地 rss-row 函数,该函数接受提供的链接和标题文本,并将此插入一个 HTML 片段中。

可以使用 GNU Qexo 库执行查询,该库提供了一个 XQuery 组件:

$ java -jar kawa-1.9.1.jar --xquery --main simplerss.xql

输出基本等同于前面在其他解决方案中已经看到的示例,因此,让我们更进一步,对原始的、基本的示例进行扩展。



回页首[/td]

[tr][td]
[/tr]

对输出进行排序

对输出的新闻项进行排序是最简单的初始步骤之一。使用传统解决方案时,排序可能很难,虽然在某些情况下并非不可能。但 XQuery 包括对许多不同数据类型的支持,这意味着您可以对源 XML 文件中的各种数据进行排序。

如果使用新闻提要,那么对不同信息片上的项进行排序就存在更多的可能。典型模型是按日期对项进行排序,这样就可以按照时间顺序阅读条目。

要添加对输出的排序,只需将一个代码行添加到

rss-summary
函数中的
for
let
where
order by
return
(FLOWR) 表达式中,对输出进行排序即可,如清单 7 中所示。


清单 7. 添加对输出的排序

declare function local:rss-summary ($url)
{
for$b in doc($url)/rss/channel/item
order by $b/pubDate
return local:rss-row($b/link/text(), $b/title/text())
};

XQuery 知道将信息写入 RSS 和 Atom 文件的日期,因此它可以自动对这些信息进行排序。如果想按降序日期 —最新的项在最前面— 顺序对项进行排序,那么只需将

descending
参数添加到 order by 表达式(清单 8)中即可。


清单 8. 添加

descending
参数

declare function local:rss-summary ($url)
{
for$b in doc($url)/rss/channel/item
order by $b/pubDate descending
return local:rss-row($b/link/text(), $b/title/text())
};

在上面两个按日期进行排序的示例中,都通过选择单个标记的内容作为排序值,使用 XPath 表达式来引用单个项(在这里是 RSS 提要中的一个项)。

在通过使用 XQuery 以 HTML 形式输出单个 RSS 提要的基本系统准备就绪之后,现在需要处理多个提要。



回页首[/td]

[tr][td]
[/tr]

合并多个提要

在原始脚本中,由系统通过 rss-summary 函数调用

{local:rss-summary("planet.rss2.xml")}
中的规范来决定处理哪一个提要。

要添加更多的提要,可多次调用该函数。planet.mcslp.com 实际上是将由许多不同提要合并成的更易于显示的单个博客和提要聚合在一起。可以使用 XQuery 复制此过程,将多个提要合并在一起。

此外,将提要合并在一起时,您可能想为每个帖子添加一个标题,以便查看每个帖子的来源。清单 9 显示了一个修改过的提要输出,该输出包含来自两个提要的信息。


清单 9. 显示多个 RSS 提要 (multirss.xql)

declare function local:rss-row ($doctitle, $link, $title)
{
<li><a href="{$link}">{$doctitle}: {$title}</a></li>
};

declare function local:rss-summary ($url)
{
let $feeddoc := doc($url)

for$b in $feeddoc/rss/channel/item
order by $b/pubDate descending
return local:rss-row($feeddoc/rss/channel/title/text(), $b/link/text(), $b/title/text())

};

<html>
<body>
<b>All the news that's fit to print</b>
<hr/>

<ul>
{local:rss-summary("http://coalface.mcslp.com/wp-rss2.php")}
{local:rss-summary("http://www.mcslp.com/wp-rss2.php")}
</ul>
</body>
</html>

图 1 显示该过程的输出,即最终呈现的 HTML。


图 1. 多个 RSS 提要

连续对两个文档多次调用

rss-summary
函数时存在的问题是信息无法合并。作为替代方法,您可以逐个输出来自两个提要的信息。

要实际合并多个提要,最简单的方法是创建一个中间 XML 文档,然后可以使用 XQuery 再次解析该文档来过滤出单个信息。可以参见清单 10 中的这样一个示例。


清单 10. 使用中间文档合并多个提要 (multirss2.xql)

declare function local:buildmergerow ($doctitle, $item)
{
<item>
<doctitle>{$doctitle}</doctitle>
<title>{$item/title/text()}</title>
<link>{$item/link/text()}</link>
<pubdate>{$item/pubDate/text()}</pubdate>
</item>
};

declare function local:rss-row ($item)
{
<li><a href="{$item/link/text()}">{$item/doctitle/text()}:
{$item/title/text()}</a></li>
};

declare function local:rss-summary ($url)
{
let $feeddoc := doc($url)

for$b in $feeddoc/rss/channel/item
return local:buildmergerow($feeddoc/rss/channel/title/text(), $b)
};

<html>
<body>
<b>All the news that's fit to print</b>
<hr/>

<ul>

{
let $feedlist := ("http://coalface.mcslp.com/wp-rss2.php",
"http://www.mcslp.com/wp-rss2.php")

let $merged := for$url in $feedlist
return local:rss-summary($url)

return for$item in $merged
order by $item/pubdate descending
return local:rss-row($item)

}

</ul>
</body>
</html>

清单 10 中示例的工作方式比以前的示例更复杂一些,但仍然十分简单。该示例可拆分成四个组成部分,三个函数和主要执行块,每个组成部分都有不同的作用:

  • buildmergerow()
    函数接受提要标题和单个项,并为包含提要标题、项标题、链接和发布日期信息的每个项创建一个中间 XML 结构。
  • rss-summary()
    函数的工作方式差不多和之前一样,处理每个项的单个提要,但在每个项上调用 buildmergerow()。
  • rss-row()
    函数将准 RSS XML 格式的项格式化为 HTML 列表项。

主块提供了一个提要列表。您可以遍历该提要列表,处理每个提要,然后返回该过程的输出,将它放置在 $merged 变量中。因为要将整个

for
循环的输出指定给变量,所以结果就变成您将准 RSS 项 XML 放置在用于所有提要的变量中。一旦结束该过程,$merge 的值将包含来自 XML 格式的所有 RSS 提要的所有项。

然后,这一部分中的最后一个 for循环将在这个准 RSS 列表上进行迭代,对项进行排序,并使用 rss-row() 函数对信息进行格式化。因为已经将来自所有提要的所有项合并成单个 $merged 列表,所以可以使用相同参数(在这里为日期)对所有项进行排序,并按反时间顺序生成列表的适当合并列表。

可以参见图 2 中显示的过程结果。


图 2. 合并的 RSS 提要



回页首[/td]

[tr][td]
[/tr]

同时处理两种提要类型

前面合并一个以上 RSS 提要的示例实际上提供了如何解决不同提要类型的解决方案。可以使用相同的中间处理技巧将 RSS 和 Atom 提要解析成中间 XML 格式,然后处理该中间 XML 文档,生成您想要的信息。

在此实例中,有少许障碍需要克服。第一个问题是 Atom 使用源 XML 文档中的名称空间,因此必须声明 Atom 名称空间来正确提取信息。

第二个问题是确定想要访问的文档类型。尽管通常从提要或文档名称就可以很清楚地知道它们的类型,但还可以使用 XQuery 中的 if 语句寻找特定标记,然后执行适当的解析函数,从文件中提取信息。在清单 11 中可以看见代码片段中该语句的示例。


清单 11. 确定 提要类型信息的

if
语句

if (count($feeddoc/atom:feed/atom:entry) > 0)
then
local:parse-atom($feeddoc)
else
local:parse-rss($feeddoc)

清单 12 显示了完整的清单。此解决方案对以前的解决方案进行了修改。现在有两个函数,一个用于 Atom 提要,一个用于 RSS 提要,而不是只有一个用来构建中间文档的函数。与以前的解决方案类似,现在有用来处理提要(因为用于每种提要的 XPath 规范是不同的)的单独函数,还有用来构建中间 XML 文档的相应函数。


清单 12. 合并不同的提要类型 (multifeed.xql)

declare namespace atom = "http://purl.org/atom/ns#";

declare function local:atombuildmergerow ($doctitle, $item)
{
<item>
<doctitle>{$doctitle}</doctitle>
<title>{ $item/atom:title/text() }</title>
<link>{$item/atom:id/text()}</link>
<pubdate>{$item/atom:modified/text()}</pubdate>
</item>
};

declare function local:rssbuildmergerow ($doctitle, $item)
{
<item>
<doctitle>{$doctitle}</doctitle>
<title>{$item/title/text()}</title>
<link>{$item/link/text()}</link>
<pubdate>{$item/pubDate/text()}</pubdate>
</item>
};

declare function local:rss-row ($item)
{
<li><a href="{$item/link/text()}">{$item/doctitle/text()}:
{$item/title/text()}</a></li>
};

declare function local:parse-rss($feeddoc)
{
for$b in $feeddoc/rss/channel/item
return local:rssbuildmergerow($feeddoc/rss/channel/title/text(), $b)
};

declare function local:parse-atom($feeddoc)
{
for$b in $feeddoc/atom:feed/atom:entry
return local:atombuildmergerow($feeddoc/atom:feed/atom:title/text(), $b)
};

<html>
<body>
<b>All the news that's fit to print</b>
<hr/>

<ul>

{
let $feedlist := ("coalface.rss2.xml",
"mcslp.atom.xml")

let $merged := for$url in $feedlist
let $feeddoc := doc($url)
return if (count($feeddoc/atom:feed/atom:entry) > 0)
then
local:parse-atom($feeddoc)
else
local:parse-rss($feeddoc)

return for$item in $merged
order by $item/title
return local:rss-row($item)

}

</ul>
</body>
</html>

在这里,该脚本使用了文件的本地副本来节约时间。让我们使用不同的 XQuery 处理器来解析不包含内置 URL 访问器方法的内容(如 Qexo 工具包所做)。例如,如果使用 Saxon XQuery 处理器,那么可以按如下所示运行脚本:

$ java -cp /usr/share/saxon/lib/saxon8.jar net.sf.saxon.Query multifeed.xql

图 3 显示了来自提要的输出。该输出应该等同于图 2 的输出。不同之处并不在生成的结果上,而在于您使用 Atom 和 RSS 提要生成了该信息。


图 3. 合并的 RSS 和 Atom 摘要



回页首[/td]

[tr][td]
[/tr]

结束语

[/td]
[td]分享这篇文章……

提交到 Digg
发布到 del.icio.us
Slashdot 一下!

从本文可以了解 RSS 和 Atom 提要的 XQuery 处理的基本知识,了解如何将一个提要转换成一个 HTML 文档。然后,可以生成一个以符合您需要的格式输出信息的更完善解决方案,其中包括多个提要的排序和合并,甚至还包括处理不同提要和源信息类型。

XQuery 提供了处理 XML 文件的灵活方法。一些人发现,从语法方面说,此方法更易于遵循。当然,某些 XQuery 功能,比如说创建单个 XML 中间文档的灵活性,以便再次解析以处理不同源和输入格式,有助于解决处理 XML 文件时将体验到的一些问题。




回页首[/td]

[tr][td]
[/tr]

下载

描述 名字 大小 下载方法
本文的样例代码 x-xqueryrss.zip 3KB HTTP
关于下载方法的信息


参考资料

学习

  • 您可以参阅本文在 develperWorks 全球网站上的 英文原文

  • RSS 1.0 规范:阅读有关 Atom 的信息,Atom 是一种基于 XML 的 Web 内容和元数据连锁格式。

  • RSS 2.0 规范:通过阅读了解关于此 Web 内容连锁格式和 XML 方言的更多信息。所有 RSS 文件都必须遵守 XML 1.0 规范,正如 World Wide Web Consortium (W3C) 网站上公布的那样。

  • RSS 2.0 和 Atom:比较 RSS 2.0 和 Atom 1.0 连锁语言之间的不同。

  • RSS 入门简介(Vincent Lauria,developerWorks,2006 年 3 月):了解有关 RSS、Atom 和提要阅读器的信息,包括了解 RSS 如此流行的原因以及它的优点。了解什么样的提要阅读器是可用的,以及哪种提要阅读器可以满足您的需要。

  • RSS(文件格式):阅读 Wikipedia 的优秀文章,这些文章详细描述了 RSS 文件格式的历史和差异。

  • XQuery 1.0 规范:了解有关此 XML 语言的更多信息,该语言灵活使用 XML 结构表达跨各种 XML 数据源的查询。

  • Web 的将来是语义的(Naveen Balani,developerWorks,2005 年 10 月)研究 Semantic Web 技术的基础,以及如何可以充分利用基于本体论的开发。

  • XSLT: Working with XML and HTML(Khun Yee Fung,Addison-Wesley,2000 年 12 月):获得有关 XSLT 的全面的参考资料和教程。

  • 使用 XML Query 处理 XML(Nicholas Chase,developerWorks,2007 年 3 月):了解有关 XQuery 1.0 的更多信息,以及如何从支持 XQuery 的数据库中存储的 XML 文档中检索信息。

  • XSLT 函数:请参阅来自 w3school.com 的大量参考资料。

  • IBM XML 认证:了解如何能够成为 IBM 认证的 XML 和相关技术方面的开发人员。

  • XML 技术文档库:参阅 developerWorks XML 专区,获得大量技术文章和技巧、教程、标准和 IBM 红皮书。

  • developerWorks 技术事件和网络广播:通过这些会话获得最新的技术进展。

  • developerWorks XML 专区:学习有关 XML 的所有知识。

  • 技术书店:浏览关于这些技术和其他技术主题的书籍。


获得产品和技术

  • 点赞
  • 收藏
  • 分享
  • 文章举报
nuanfeng2008 发布了1 篇原创文章 · 获赞 0 · 访问量 505 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: