[SOLVED] Openfire indicates of one node item, when it has more

Greetings.

I am working on a Chawan script to download data from XMPP PubSub nodes.

#!/usr/bin/env python3
# coding: utf-8
#
# Usage:
#
# printf "xmpp:pubsub.movim.eu?;node=berlin-xmpp-meetup" | python pubsub.py > berlin-xmpp-meetup.pubsub

import asyncio
import configparser
import datetime
import os
import select
import sys
from urllib.parse import urlparse
import xml.etree.ElementTree as ET

class Chawan:

    def directives(cha_control, content=None, content_type=None, status_code=None) -> None:
        if status_code:
            sys.stdout.write(f"Status: {status_code}\n")
        sys.stdout.write(f"Cha-Control: {cha_control}\n")
        if content_type:
            sys.stdout.write(f"Content-Type: {content_type}\n")
        if content:
            sys.stdout.write("\n")
            sys.stdout.write(content)
            sys.stdout.write("\n")
        sys.stdout.flush()
        sys.exit()

try:
    from slixmpp import ClientXMPP
    from slixmpp.exceptions import IqError, IqTimeout
    from slixmpp.stanza.iq import Iq
    #from slixmpp.xmlstream import ET
except Exception as e:
    cha_control = f"ConnectionError InternalError {str(e)}"
    content = content_type = status_code = None
    Chawan.directives(cha_control, content, content_type, status_code)

class Xmpp:

    async def pubsub(
        client_xmpp: ClientXMPP, jid_bare: str, node_name=None, item_id=None
        ) -> dict:
        result = {}
        iq = None
        try:
            if jid_bare and node_name and item_id:
                iq = await client_xmpp.plugin["xep_0060"].get_item(
                    jid_bare, node_name, item_id, timeout=5)
            elif jid_bare and node_name:
                iq = await client_xmpp.plugin["xep_0060"].get_items(
                    jid_bare, node_name, timeout=15)
            elif jid_bare:
                iq = await client_xmpp.plugin["xep_0060"].get_nodes(
                    jid_bare, timeout=10)
        except (IqError, IqTimeout) as e:
            error_condition = e.iq["error"]["condition"]
            error_text = e.iq["error"]["text"]
        if iq:
            if "pubsub" in iq:
                #if "items" in iq["pubsub"] and "item" in iq["pubsub"]["items"]:
                if iq["pubsub"]["items"]["item"]["payload"] is not None:
                    result = {"content" : str(iq["pubsub"]),
                              "message" : "Success",
                              "error"   : False}
                else:
                    # This is not an error. It is a state of event of an empty node.
                    result = {"content" : None,
                              "message" : "PubSub node appears to be empty",
                              "error"   : True}
            elif "error" in iq:
                result = {"content" : None,
                          "message" : f"{error_condition}: {error_text}",
                          "error"   : True}
            else:
                result = {"content" : None,
                          "message" : f"Unknown error: {str(iq)}",
                          "error"   : True}
        else:
            result = {"content" : None,
                      "message" : "Unknown error: Stanza IQ is empty",
                      "error"   : True}
        return result

if __name__ == "__main__":
    directory_data = (
        os.environ.get("CHA_DATA_DIR") or
        os.path.join(os.environ.get("HOME"), ".local/share/chawan"))
    credentials = os.path.join(directory_data, "credentials.ini")
    config = configparser.ConfigParser()
    config.read(credentials)
    if ("xmpp" in config and
        "address" in config["xmpp"] and
        "password" in config["xmpp"]):
        address = config["xmpp"]["address"]
        password = config["xmpp"]["password"]
        stdin_input = sys.stdin.read()
        if stdin_input:
            uri = stdin_input
        else:
            uri_scheme = os.environ.get("MAPPED_URI_SCHEME")
            uri_path = os.environ.get("MAPPED_URI_PATH")
            uri_query = os.environ.get("MAPPED_URI_QUERY")
            uri = f"{uri_scheme}:{uri_path}?{uri_query}"
        fragmented_uri = urlparse(uri)
        if fragmented_uri.scheme == "xmpp":
            jid_bare = fragmented_uri.path
            item_id = node_name = None
            for parameter in fragmented_uri.query.split(";"):
                if parameter.startswith("node="):
                    node_name = parameter[5:]
                if parameter.startswith("item="):
                    item_id = parameter[5:]
            if jid_bare or jid_bare and node_name:
                client_xmpp = ClientXMPP(address, password)
                client_xmpp.register_plugin("xep_0060")
                #client_xmpp.register_plugin("xep_0199")
                #client_xmpp.connect()
                # ERROR:slixmpp.features.feature_mechanisms.mechanisms:No appropriate login method.
                loop = asyncio.get_event_loop()
                #rtt = loop.run_until_complete(client_xmpp.plugin["xep_0199"].ping())
                #if rtt:
                try:
                    client_xmpp.connect()
                    #result = asyncio.run(
                    #    Xmpp.pubsub(client_xmpp, jid_bare, node_name, item_id))
                    result = loop.run_until_complete(
                        Xmpp.pubsub(client_xmpp, jid_bare, node_name, item_id))
                    client_xmpp.disconnect(
                        ignore_send_queue=False,
                        reason="Chawan: Receiving PubSub data was completed.",
                        wait=2.0)
                    # TODO if no items in result node (an empty node)
                    if result["error"]:
                        message = result["message"]
                        cha_control = f"ConnectionError ConnectionRefused {message}."
                        content = content_type = status_code = None
                    else:
                        """
                        xml = ET.fromstring(result["content"])
                        namespaces = {
                            "atom"   : "http://www.w3.org/2005/Atom",
                            "pubsub" : "http://jabber.org/protocol/pubsub",
                            "xhtml"  : "http://www.w3.org/1999/xhtml"}
                        for namespace in namespaces:
                            ET.register_namespace(
                                namespace, namespaces[namespace])
                        ET.indent(xml, space="  ", level=0)
                        content = ET.tostring(xml, encoding="unicode")
                        """
                        content = result["content"]
                        cha_control = "ControlDone"
                        content_type = "application/pubsub+xml"
                        status_code = "200"
                except Exception as e:
                    message = f"Check whether credentials or XMPP URI are valid; {str(e)}"
                    cha_control = f"ConnectionError ConnectionRefused {message}."
                    content = content_type = status_code = None
            else:
                message = f"Jabber ID or Node Name appear to be missing: {uri}"
                cha_control = f"ConnectionError InvalidURL {message}."
                content = content_type = status_code = None
        else:
            message = f"Invalid XMPP PubSub Query URI: {uri}"
            cha_control = f"ConnectionError InvalidURL {message}."
            content = content_type = status_code = None
    else:
        message = f"XMPP credentials are missing {credentials}"
        cha_control = f"ConnectionError InternalError {message}."
        content = content_type = status_code = None
    Chawan.directives(cha_control, content, content_type, status_code)

Interestingly, when downloading from xmpp:publisher@slixfeed.goodbytes.im?;node=urn:xmpp:microblog:0 only a single item is downloaded, which is the most recent uploaded item.

Yet, when downloading from XMPP URI xmpp:publisher@slixfeed.goodbytes.im?;node=urn:xmpp:microblog:0;item=2026-01-01-recommended-xmpp-desktop-chat-clients it is possible to retrieve the data, albeit it is not appear to be listed, as Openfire indicates that only a single item is present.

printf “xmpp:publisher@slixfeed.goodbytes.im?;node=urn:xmpp:microblog:0;item=2026-01-01-recommended-xmpp-desktop-chat-clients” | python pubsub.cgi
Status: 200
Cha-Control: ControlDone
Content-Type: application/pubsub+xml

<pubsub xmlns="http://jabber.org/protocol/pubsub"><items node="urn:xmpp:microblog:0"><item id="2026-01-01-recommended-xmpp-desktop-chat-clients"><entry xmlns="http://www.w3.org/2005/Atom" xml:lang="en-ps"><title type="text">Recommended XMPP desktop chat clients</title><summary type="text">Recommended XMPP chat clients for desktop.</summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml">
<p>This is a sample article that showcases a custom XSLT stylesheet which is
intended for multimedia media galleries.</p>
<p>This gallery is realized by setting preambles of &quot;links&quot; with rel &quot;related&quot;
and &quot;image&quot; of the same title.</p>
<pre class="code rst literal-block"><code>title,href,rel,type<span class="whitespace">
</span>Converse, /graphics/conversejs.svg, image, image/svg+xml<span class="whitespace">
</span>Converse, https://conversejs.org, related</code></pre>
<p>Schapps recommends and endorses these chat clients, although there is no attempt
to judge or compare them based on any criterion other than freedom; the software
herein are listed by the ease of installation and common purposes for home
computers.</p>
</div>
</content><category term="chat" label="Chat" scheme="/tag" /><category term="jabber" label="Jabber" scheme="/tag" /><category term="voip" label="VoIP" scheme="/tag" /><category term="xmpp" label="XMPP" scheme="/tag" /><link title="Recommended XMPP desktop chat clients" href="/posts/2026-01-01-recommended-xmpp-desktop-chat-clients" rel="base" /><link title="Recommended XMPP desktop chat clients" href="/posts/2026-01-01-recommended-xmpp-desktop-chat-clients/index.atom" rel="self" /><link title="Download this article" href="/posts/2026-01-01-recommended-xmpp-desktop-chat-clients/enclosures.meta4" type="application/metalink4-xml" rel="metalink" /><link title="Article source" href="/posts/2026-01-01-recommended-xmpp-desktop-chat-clients/source.rst" type="text/x-rst" rel="source" /><link title="17 XMPP chat clients" href="/posts/2026-01-01-recommended-xmpp-desktop-chat-clients/clients.ms.txt" type="text/plain" rel="microsummary" /><link title="css" href="/css/gallery.css" type="text/css" rel="stylesheet" /><link title="html" href="/xslt/page-gallery.xslt" type="application/xslt+xml" rel="stylesheet" /><link title="The motto of XMPP" href="/graphics/xmpp_motto.svg" type="image/svg+xml" rel="photo" /><link title="The logo of the protocol XMPP" href="/graphics/xmpp.svg" type="image/svg+xml" rel="avatar" /><link title="Psi" href="/graphics/psi.svg" type="image/svg+xml" rel="image" /><link title="Miranda NG" href="/graphics/miranda.svg" type="image/svg+xml" rel="image" /><link title="UWPX" href="/graphics/uwpx.svg" type="image/svg+xml" rel="image" /><link title="Pidgin" href="/graphics/pidgin.svg" type="image/svg+xml" rel="image" /><link title="Converse" href="/graphics/conversejs.svg" type="image/svg+xml" rel="image" /><link title="CoyIM" href="/graphics/coyim.svg" type="image/svg+xml" rel="image" /><link title="Beagle IM" href="/graphics/beagle.svg" type="image/svg+xml" rel="image" /><link title="Monal" href="/graphics/monal.svg" type="image/svg+xml" rel="image" /><link title="Spark" href="/graphics/spark.svg" type="image/svg+xml" rel="image" /><link title="Pàdé" href="/graphics/pade.svg" type="image/svg+xml" rel="image" /><link title="Fluux" href="/graphics/fluux.svg" type="image/svg+xml" rel="image" /><link title="Smuxi" href="/graphics/smuxi.svg" type="image/svg+xml" rel="image" /><link title="Kaidan" href="/graphics/kaidan.svg" type="image/svg+xml" rel="image" /><link title="Gajim" href="/graphics/gajim.svg" type="image/svg+xml" rel="image" /><link title="Dino" href="/graphics/dino.svg" type="image/svg+xml" rel="image" /><link title="Squawk" href="/graphics/squawk.svg" type="image/svg+xml" rel="image" /><link title="Swift" href="/graphics/swift.svg" type="image/svg+xml" rel="image" /><link title="Prose" href="/graphics/prose.svg" type="image/svg+xml" rel="image" /><link title="Dergchat" href="/graphics/dergchat.svg" type="image/svg+xml" rel="image" /><link title="Beagle IM" href="https://beagle.im" rel="related" /><link title="Converse" href="https://conversejs.org" rel="related" /><link title="CoyIM" href="https://coy.im" rel="related" /><link title="Dino" href="https://dino.im" rel="related" /><link title="Dergchat" href="https://codeberg.org/Mizah/Dergchat" rel="related" /><link title="Fluux" href="https://github.com/processone/fluux-messenger" rel="related" /><link title="Gajim" href="https://gajim.org" rel="related" /><link title="Kaidan" href="https://kaidan.im" rel="related" /><link title="Miranda NG" href="https://miranda-ng.org" rel="related" /><link title="Monal" href="https://monal-im.org" rel="related" /><link title="Pàdé" href="https://igniterealtime.org/projects/pade/" rel="related" /><link title="Pidgin" href="https://pidgin.im" rel="related" /><link title="Psi" href="https://psi-im.org" rel="related" /><link title="Prose" href="https://prose.org" rel="related" /><link title="Spark" href="https://igniterealtime.org/projects/spark/" rel="related" /><link title="Squawk" href="https://macaw.me/projects/squawk/" rel="related" /><link title="Smuxi" href="https://smuxi.im" rel="related" /><link title="Swift" href="https://swift.im" rel="related" /><link title="UWPX" href="https://uwpx.org" rel="related" /><link title="XMPP as the internet" href="/posts/2024-11-05-xmpp-as-the-internet" rel="related" /><link title="Recommended XMPP mobile chat clients" href="/posts/2026-01-01-recommended-xmpp-mobile-chat-clients" rel="related" /><link title="CoyIM" href="https://coy.im/feed.xml" rel="feed" /><link title="Dino" href="https://dino.im/index.xml" rel="feed" /><link title="Gajim" href="https://gajim.org/index.xml" rel="feed" /><link title="Kaidan" href="https://kaidan.im/atom.xml" rel="feed" /><link title="Miranda NG" href="https://miranda-ng.org/index.xml" rel="feed" /><link title="Monal" href="https://monal-im.org/index.xml" rel="feed" /><link title="Smuxi" href="https://smuxi.im/news/index.rss" rel="feed" /><link title="Swift" href="https://swift.im/wordpress/index.php/feed/atom/" rel="feed" /><link href="/posts/2026-01-01-recommended-xmpp-desktop-chat-clients/index.atom" type="application/atom+xml" rel="alternate" /><link href="xmpp:publisher@slixfeed.goodbytes.im?;node=urn:xmpp:microblog:0;item=2026-01-01-recommended-xmpp-desktop-chat-clients" type="application/pubsub+xml" rel="self" /><link href="xmpp:publisher@slixfeed.goodbytes.im?;node=urn:xmpp:microblog:0;item=2026-01-01-recommended-xmpp-desktop-chat-clients" type="application/pubsub+xml" rel="alternate" /><link title="comments" href="xmpp:discussions.slixfeed.goodbytes.im?;node=publisher@slixfeed.goodbytes.im/urn:xmpp:microblog:0/2026-01-01-recommended-xmpp-desktop-chat-clients" type="application/pubsub+xml" rel="replies" /><link title="comments" href="xmpp:discussions.slixfeed.goodbytes.im?;node=publisher@slixfeed.goodbytes.im/urn:xmpp:microblog:0/2026-01-01-recommended-xmpp-desktop-chat-clients" type="application/pubsub+xml" rel="replies" /><link title="Recommended Linux desktop distros" href="xmpp:publisher@slixfeed.goodbytes.im?;node=urn:xmpp:microblog:0;item=2026-01-01-recommended-linux-desktop-distros" rel="previous" /><link title="Recommended XMPP mobile chat clients" href="xmpp:publisher@slixfeed.goodbytes.im?;node=urn:xmpp:microblog:0;item=2026-01-01-recommended-xmpp-mobile-chat-clients" rel="next" /><published>2026-01-01 0:00:00 UTC</published></entry></item></items></pubsub>

Could it be that this item, and other items, are temporarily cached?

Apparently, these entries are temporarily cached, so there is indeed only an entry as indicated by Openfire.