使用 xslt、xpath:document() 和 mediawiki 进行递归转换

发布于 2024-07-27 03:49:45 字数 2443 浏览 2 评论 0原文

我想使用 Wikipedia API 查找包括“SQLTemplate”的法语页面:英文版中缺少“Infobox Scientifique”。 所以,我的想法是使用 xproc 处理以下文档:

http://fr.wikipedia.org/w/api.php?action=query&format=xml&list=embeddedin&eititle=Template:Infobox%20Scientifique& ;eilimit=400

和以下 xslt 样式表:

<?xml version='1.0' ?>
<xsl:stylesheet
    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
    version='1.0'
    >
<xsl:output method='text' indent="yes"/> 
<xsl:template match="/">
<xsl:apply-templates select="api"/>
</xsl:template>

<xsl:template match="api">
<xsl:for-each select="query/embeddedin/ei">
<xsl:variable name="title" select="translate(@title,&apos; &apos;,&apos;_&apos;)"/>
<xsl:variable name="english-title">
<xsl:call-template name="englishTitle"><xsl:with-param name="title" select="@title"/></xsl:call-template>
</xsl:variable>

<xsl:value-of select="$english-title"/><xsl:text>
</xsl:text>

</xsl:for-each>
</xsl:template>

<xsl:template name="englishTitle">
<xsl:param name="title"/>
<xsl:variable name="uri1" select="concat(&apos;http://fr.wikipedia.org/w/api.php?action=query&amp;format=xml&amp;prop=langlinks&amp;lllimit=500&amp;titles=&apos;,translate($title,&apos; &apos;,&apos;_&apos;))"/>
<xsl:message><xsl:value-of select="$uri1"/></xsl:message>
<xsl:message>count=<xsl:value-of select="count(document($uri1,/api/query/pages/page/langlinks/ll))"/></xsl:message>
</xsl:template>

</xsl:stylesheet>

XSLT 提取包含模板的所有文章,对于每篇文章,我想调用 Wikipedia 来获取 wiki 之间的链接。 这里模板 englishTitle 调用 xpath 函数 document()

但它总是说 count(ll)=1 而有很多节点。 (例如 http://fr.wikipedia.org/w/api.php?action=query&format=xml&prop=langlinks&lllimit=500&titles=Carl_Sagan)。

我无法处理 document() 函数返回的节点吗?

I want to use the Wikipedia API to find the French pages including the ''SQLTemplate:Infobox Scientifique'' missing in the English version. So, my idea was to process the following document with xproc:

http://fr.wikipedia.org/w/api.php?action=query&format=xml&list=embeddedin&eititle=Template:Infobox%20Scientifique&eilimit=400

and the following xslt stylesheet:

<?xml version='1.0' ?>
<xsl:stylesheet
    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
    version='1.0'
    >
<xsl:output method='text' indent="yes"/> 
<xsl:template match="/">
<xsl:apply-templates select="api"/>
</xsl:template>

<xsl:template match="api">
<xsl:for-each select="query/embeddedin/ei">
<xsl:variable name="title" select="translate(@title,' ','_')"/>
<xsl:variable name="english-title">
<xsl:call-template name="englishTitle"><xsl:with-param name="title" select="@title"/></xsl:call-template>
</xsl:variable>

<xsl:value-of select="$english-title"/><xsl:text>
</xsl:text>

</xsl:for-each>
</xsl:template>

<xsl:template name="englishTitle">
<xsl:param name="title"/>
<xsl:variable name="uri1" select="concat('http://fr.wikipedia.org/w/api.php?action=query&format=xml&prop=langlinks&lllimit=500&titles=',translate($title,' ','_'))"/>
<xsl:message><xsl:value-of select="$uri1"/></xsl:message>
<xsl:message>count=<xsl:value-of select="count(document($uri1,/api/query/pages/page/langlinks/ll))"/></xsl:message>
</xsl:template>

</xsl:stylesheet>

The XSLT extract all the articles containing the Template and for each article I wanted to call Wikipedia to get the links between the wikis. Here the template englishTitle calls the xpath function document().

But it always says that count(ll)=1 whereas there are plenty nodes. (e.g. http://fr.wikipedia.org/w/api.php?action=query&format=xml&prop=langlinks&lllimit=500&titles=Carl_Sagan ).

Can't I process the nodes returned by the document() function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

厌味 2024-08-03 03:49:46

你应该尝试:

<xsl:value-of select="count(document($uri1)/api/query/pages/page/langlinks/ll)"/>

换个方式——这是什么

translate(@title,' ','_')

意思? 问题所在:

translate(@title, ' ', '_')

不需要在 XML 属性中对单引号进行编码,除非您想使用分隔属性值的引号类型。 所有这些都是有效的:

name="foo"'foo"
name='foo'"foo'

您的整个转换可以简化为如下所示:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output method="text" /> 

  <xsl:param name="baseUrl" select="'http://fr.wikipedia.org/w/api.php?action=query&format=xml&prop=langlinks&lllimit=500&titles='" />

  <xsl:template match="ei">
    <xsl:variable name="uri" select="concat($baseUrl ,translate(@title,' ','_'))"/>
    <xsl:variable name="doc" select="document($uri)"/>

    <xsl:value-of select="$uri"/>
    <xsl:text>
</xsl:text>

    <xsl:text>count=</xsl:text>
    <xsl:value-of select="count($doc/api/query/pages/page/langlinks/ll)"/>
    <xsl:text>
</xsl:text>
  </xsl:template>

  <xsl:template match="text()" />  
</xsl:stylesheet>

让 XSLT 默认模板为您工作 - 它们在后台执行所有递归,您所要做的就是捕获要处理的节点(并通过用空模板覆盖默认的 text() 模板来防止输出不必要的文本)。

You should try:

<xsl:value-of select="count(document($uri1)/api/query/pages/page/langlinks/ll)"/>

On a different note - what is

translate(@title,' ','_')

supposed to mean? What's wrong with:

translate(@title, ' ', '_')

There is no need to encode single quotes in XML attributes unless you want to use a type of quote that delimits the attribute value. All of these are valid:

name="foo"'foo"
name='foo'"foo'

Your entire transformation can be reduced to something like this:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output method="text" /> 

  <xsl:param name="baseUrl" select="'http://fr.wikipedia.org/w/api.php?action=query&format=xml&prop=langlinks&lllimit=500&titles='" />

  <xsl:template match="ei">
    <xsl:variable name="uri" select="concat($baseUrl ,translate(@title,' ','_'))"/>
    <xsl:variable name="doc" select="document($uri)"/>

    <xsl:value-of select="$uri"/>
    <xsl:text>
</xsl:text>

    <xsl:text>count=</xsl:text>
    <xsl:value-of select="count($doc/api/query/pages/page/langlinks/ll)"/>
    <xsl:text>
</xsl:text>
  </xsl:template>

  <xsl:template match="text()" />  
</xsl:stylesheet>

Let the XSLT default templates work for you - they do all of the recursion in the background, all you have to do is catch the nodes you want to process (and prevent output of unnecessary text by overriding the default text() template with an empty one).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文