<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>scalability on stillcooking.dev</title>
    <link>https://stillcooking.dev/en/tags/scalability/</link>
    <description>Personal portfolio and technical notes</description>
    <generator>Hugo</generator>
    <language>en-US</language>
    
    <copyright>© 2026 stillcooking.dev — CC BY 4.0, https://creativecommons.org/licenses/by/4.0/</copyright>
    <lastBuildDate>Mon, 12 Oct 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://stillcooking.dev/en/tags/scalability/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Execute Console Command is a development tool, not a runtime API</title>
      <link>https://stillcooking.dev/en/topics/unreal-engine/gameplay-framework/execute-console-command-is-not-a-runtime-api/</link>
      <pubDate>Mon, 12 Oct 2026 00:00:00 +0000</pubDate>
      
      <guid isPermaLink="true">https://stillcooking.dev/en/topics/unreal-engine/gameplay-framework/execute-console-command-is-not-a-runtime-api/</guid>
      <description>Execute Console Command is declared in the Development category, but unlike Print String it carries no DevelopmentOnly flag, so nothing in a graph marks it as a development tool. In runtime code it writes every console variable at ECVF_SetByConsole, above scalability, user settings, Project Settings, device profiles and hotfixes. It reports no failure to the graph that called it, and the same string resolves differently in the editor and in Shipping.</description>
      <content:encoded><![CDATA[<p><code>Execute Console Command</code> is a development tool, and its declaration says so: the function sits in <code>Category=&quot;Development&quot;</code>. In Blueprint that category shows up as the node&rsquo;s folder in the action menu and nowhere on the node once it is in a graph. In a project&rsquo;s runtime code the node is the wrong way to change engine state. It writes every console variable (CVar) with the priority reserved for a developer typing at the console. It reports no failure to the graph that called it. And the same string can mean different things in the editor and in a Shipping build.</p>
<p>From inside a graph the node looks like an ordinary setter. It takes effect immediately in PIE, and it is the only way to write a CVar through the engine&rsquo;s general Blueprint library: <code>UKismetSystemLibrary</code> provides CVar getters but no dedicated CVar setter (<code>KismetSystemLibrary.h:609-636</code>).</p>
<figure class="bp-embed">
  <div class="bp-embed__canvas" data-bp-src="/blueprints/cvar-console-pin-repro.txt" data-bp-height="240"></div>
  <noscript>
    <p class="bp-embed__fallback">Viewing the graph requires JavaScript.</p>
    <a class="bp-embed__download" href="/blueprints/cvar-console-pin-repro.txt" download>Download Blueprint graph (.txt)</a>
  </noscript><figcaption class="bp-embed__caption">Event BeginPlay calls Execute Console Command with r.LightFunctionQuality 2. It compiles, runs in PIE, and changes nothing on screen.</figcaption></figure>
<h2 id="what-the-node-is">What the node is</h2>
<p>The declaration (<code>Engine/Classes/Kismet/KismetSystemLibrary.h:593-600</code>, UE 5.7):</p>
<div class="highlight" data-lang="cpp">
  <button type="button" class="code-copy" data-code-copy data-label="Copy" data-copied="Copied!" aria-label="Copy code to clipboard">Copy</button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Executes a console command, optionally on a specific controller
</span></span></span><span class="line"><span class="cl"><span class="cm"> * 
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param   Command         Command to send to the console
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param   SpecificPlayer  If specified, the console command will be routed through the specified player
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="n">UFUNCTION</span><span class="p">(</span><span class="n">BlueprintCallable</span><span class="p">,</span> <span class="n">Category</span><span class="o">=</span><span class="s">&#34;Development&#34;</span><span class="p">,</span><span class="n">meta</span><span class="o">=</span><span class="p">(</span><span class="n">WorldContext</span><span class="o">=</span><span class="s">&#34;WorldContextObject&#34;</span><span class="p">,</span> <span class="n">CallableWithoutWorldContext</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">ENGINE_API</span> <span class="kt">void</span> <span class="n">ExecuteConsoleCommand</span><span class="p">(</span><span class="k">const</span> <span class="n">UObject</span><span class="o">*</span> <span class="n">WorldContextObject</span><span class="p">,</span> <span class="k">const</span> <span class="n">FString</span><span class="o">&amp;</span> <span class="n">Command</span><span class="p">,</span> <span class="k">class</span> <span class="nc">APlayerController</span><span class="o">*</span> <span class="n">SpecificPlayer</span> <span class="o">=</span> <span class="nb">NULL</span> <span class="p">);</span></span></span></code></pre></div></div>
<p>The return type is <code>void</code>, and the comment says nothing about priorities, validation, or build configurations, because the function leaves all of them to the console code it calls.</p>
<p>The engine has a more explicit way to mark development nodes, and uses it in the same category. <code>Print String</code> is also declared in <code>Development</code>, but with <code>DevelopmentOnly</code> in its metadata (<code>KismetSystemLibrary.h:561</code>). A node with that flag gets a <em>Development Only</em> banner in the graph, and the banner&rsquo;s tooltip says the node is treated as disabled in Shipping and Test builds cooked from a commandlet (<code>Editor/GraphEditor/Private/SGraphNode.cpp:1086-1088</code>). <code>Execute Console Command</code> has no such flag. In a graph it looks like any gameplay node, and it runs in Shipping.</p>
<p>Internally the node hands the string to <code>IConsoleManager::ProcessUserConsoleInput</code>, the function that handles a line typed into the console, and falls back to the player controller and <code>GEngine-&gt;Exec</code> when that function does not recognize it (<code>Engine/Private/KismetSystemLibrary.cpp:547-567</code>). In effect it types into the console on the graph&rsquo;s behalf.</p>
<h2 id="it-writes-as-the-developer">It writes as the developer</h2>
<p>When the string names a CVar, <code>ProcessUserConsoleInput</code> sets it at a fixed priority (<code>Core/Private/HAL/ConsoleManager.cpp:3076</code>):</p>
<div class="highlight" data-lang="cpp">
  <button type="button" class="code-copy" data-code-copy data-label="Copy" data-copied="Copied!" aria-label="Copy code to clipboard">Copy</button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">CVar</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="o">*</span><span class="n">Param2</span><span class="p">,</span> <span class="n">ECVF_SetByConsole</span><span class="p">);</span></span></span></code></pre></div></div>
<p>Every CVar stores the priority of its last successful write, and a new write lands only if its priority is the same or higher (<code>NewPri &gt;= OldPri</code>, <code>ConsoleManager.cpp:272</code>). The enum lists the priorities from lowest to highest (<code>Core/Public/HAL/IConsoleManager.h:142-175</code>). The table below shows the ones used to configure a shipped game, plus the one the node uses:</p>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>Priority</th>
        <th>Value</th>
        <th>Written by</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>Scalability</code></td>
        <td><code>0x02</code></td>
        <td>quality levels from <code>Scalability.ini</code></td>
      </tr>
      <tr>
        <td><code>GameSetting</code></td>
        <td><code>0x03</code></td>
        <td><code>UGameUserSettings</code></td>
      </tr>
      <tr>
        <td><code>ProjectSetting</code></td>
        <td><code>0x04</code></td>
        <td>Project Settings</td>
      </tr>
      <tr>
        <td><code>SystemSettingsIni</code></td>
        <td><code>0x05</code></td>
        <td><code>[ConsoleVariables]</code> in <code>Engine.ini</code></td>
      </tr>
      <tr>
        <td><code>DeviceProfile</code></td>
        <td><code>0x07</code></td>
        <td><code>DeviceProfiles.ini</code></td>
      </tr>
      <tr>
        <td><code>Hotfix</code></td>
        <td><code>0x0B</code></td>
        <td>hotfixes</td>
      </tr>
      <tr>
        <td><code>Console</code></td>
        <td><code>0x0F</code></td>
        <td>the editor UI and the interactive console</td>
      </tr>
    </tbody>
  </table>
</div>
<p><code>Console</code> is the highest value in the enum. After one call to the node, every layer in the table loses to the console value, and none of them has a code path that removes the console entry again.</p>
<p>The engine&rsquo;s own settings code writes with an explicit, lower priority. This is how <code>UGameUserSettings</code> applies VSync (<code>Engine/Private/GameUserSettings.cpp:460-461</code>):</p>
<div class="highlight" data-lang="cpp">
  <button type="button" class="code-copy" data-code-copy data-label="Copy" data-copied="Copied!" aria-label="Copy code to clipboard">Copy</button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">static</span> <span class="k">auto</span> <span class="n">CVar</span> <span class="o">=</span> <span class="n">IConsoleManager</span><span class="o">::</span><span class="n">Get</span><span class="p">().</span><span class="n">FindConsoleVariable</span><span class="p">(</span><span class="n">TEXT</span><span class="p">(</span><span class="s">&#34;r.VSync&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="n">CVar</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="n">IsVSyncEnabled</span><span class="p">(),</span> <span class="n">ECVF_SetByGameSetting</span><span class="p">);</span></span></span></code></pre></div></div>
<p>Quality levels go through <code>Scalability::SetQualityLevels</code>, which writes each group at <code>ECVF_SetByScalability</code> (<code>Engine/Private/Scalability.cpp:446</code>). The low position is deliberate. The enum comment says scalability is <em>“lower priority than game settings so it&rsquo;s easier to override partially”</em> (<code>IConsoleManager.h:148</code>). The layers are meant to override each other in a fixed order, with the console on top for the developer. A runtime <code>Execute Console Command</code> puts shipped code in the developer&rsquo;s seat.</p>
<p>A graph that sends <code>r.VSync 0</code> through the node makes the player&rsquo;s VSync setting ineffective for the rest of the session, because <code>UGameUserSettings</code> writes at <code>GameSetting</code> and loses to the console.</p>
<h3 id="the-case-that-prompted-this-post">The case that prompted this post</h3>
<p>This post came out of a project where a third-party plugin sets <code>r.LightFunctionQuality</code> with a console command from its Blueprint, while the game&rsquo;s graphics menu is built on the engine quality levels. Every time the player applies the quality settings, the log gets this line:</p>
<div class="highlight" data-lang="log">
  <button type="button" class="code-copy" data-code-copy data-label="Copy" data-copied="Copied!" aria-label="Copy code to clipboard">Copy</button><pre tabindex="0" class="ue-log"><code><span class="ue-log__line ue-log__line--warning"><span class="ue-log__cat">LogConsoleManager</span>: <span class="ue-log__sev ue-log__sev--warning">Warning</span>: <span class="ue-log__msg">Setting the console variable &#39;r.LightFunctionQuality&#39; with &#39;SetByScalability&#39; was ignored as it is lower priority than the previous &#39;SetByConsole&#39;. Value remains &#39;2&#39;</span>
</span></code></pre>
</div>
<p>Typing the CVar name into the console without a value prints its history (<code>ConsoleManager.cpp:3093-3095</code>). With quality on Low:</p>
<div class="highlight" data-lang="text">
  <button type="button" class="code-copy" data-code-copy data-label="Copy" data-copied="Copied!" aria-label="Copy code to clipboard">Copy</button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">HISTORY
</span></span><span class="line"><span class="cl">Constructor: 2
</span></span><span class="line"><span class="cl">Scalability: 0
</span></span><span class="line"><span class="cl">Console: 2
</span></span><span class="line"><span class="cl">r.LightFunctionQuality = &#34;2&#34;      LastSetBy: Console</span></span></code></pre></div></div>
<p>The quality settings do their job. <code>Set</code> records the history before it checks the priority (<code>ConsoleManager.cpp:1342</code> and <code>:1347</code>), so the scalability write is there, and on Cinematic its line reads <code>Scalability: 1</code>. <code>Console: 2</code> outranks it either way. That <code>2</code> is also the constructor value: the plugin writes the engine default back.</p>
<p>The engine reads this CVar in one place, and the check is <code>&lt;= 0</code> (<code>Engine/Private/ShowFlags.cpp:462</code>):</p>
<div class="highlight" data-lang="cpp">
  <button type="button" class="code-copy" data-code-copy data-label="Copy" data-copied="Copied!" aria-label="Copy code to clipboard">Copy</button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="k">auto</span> <span class="n">ICVar</span> <span class="o">=</span> <span class="n">IConsoleManager</span><span class="o">::</span><span class="n">Get</span><span class="p">().</span><span class="n">FindTConsoleVariableDataInt</span><span class="p">(</span><span class="n">TEXT</span><span class="p">(</span><span class="s">&#34;r.LightFunctionQuality&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">ICVar</span><span class="o">-&gt;</span><span class="n">GetValueOnGameThread</span><span class="p">()</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">EngineShowFlags</span><span class="p">.</span><span class="n">SetLightFunctions</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p>Medium and higher quality levels request <code>1</code>, which behaves exactly like <code>2</code>. Low requests <code>0</code> (<code>Engine/Config/BaseScalability.ini:133</code>), which switches light functions off, and that is the value the console write blocks. The override only has a cost on Low, the quality level a player picks to reduce frame time.</p>
<h2 id="it-reports-nothing">It reports nothing</h2>
<p>The node returns <code>void</code>, so the graph cannot branch on the result. When the call itself fails, the failure goes to the log:</p>
<ul>
<li>A misspelled name: <code>ProcessUserConsoleInput</code> finds no CVar and returns <code>false</code> (<code>ConsoleManager.cpp:2968-2972</code>). The string falls through to the player controller, which prints <code>Command not recognized: …</code> (<code>Engine/Private/Player.cpp:58</code>).</li>
<li>A read-only CVar: the console prints <code>Error: … is read only!</code> (<code>ConsoleManager.cpp:3071</code>) and writes nothing.</li>
</ul>
<p>Nothing checks the string at compile time either. <code>Command</code> is an <code>FString</code> pin, and neither the C++ compiler nor the Blueprint compiler knows that it names a CVar, so a typo compiles as cleanly as a correct name.</p>
<p>A call that succeeds is harder to trace. Its effect shows up when the quality settings or <code>UGameUserSettings</code> later try to write the same CVar and lose. The warning then appears on the settings side, in a different system and often long after the call that caused it.</p>
<p>In a default Shipping build none of these lines are printed, because <code>NO_LOGGING</code> is defined as <code>!USE_LOGGING_IN_SHIPPING</code> (<code>Core/Public/Misc/Build.h:351</code>). The failures still happen.</p>
<h2 id="its-meaning-depends-on-the-build">Its meaning depends on the build</h2>
<p>PIE runs an editor build, and a packaged game resolves the same string differently.</p>
<p>Cheat CVars are switched off. <code>DISABLE_CHEAT_CVARS</code> is defined as <code>(UE_BUILD_SHIPPING || (UE_BUILD_TEST &amp;&amp; !ALLOW_CHEAT_CVARS_IN_TEST))</code> (<code>Core/Public/Misc/Build.h:440</code>), and under it <code>ProcessUserConsoleInput</code> returns <code>false</code> for any CVar flagged <code>ECVF_Cheat</code> without touching the value (<code>ConsoleManager.cpp:2974-2977</code>). The same node with the same string sets the CVar in PIE and does nothing in Shipping.</p>
<p>Development commands are compiled out. When the string names a command rather than a CVar, Shipping may not have its handler: <code>UEngine::Exec_Dev</code> wraps its whole body in <code>#if !UE_BUILD_SHIPPING</code> (<code>Engine/Private/UnrealEngine.cpp:5450</code>), so a command that works in PIE has no handler in the shipped game.</p>
<p>The commands that could fix the priority are developer tools too. <code>SetCVar … -setby=</code> and <code>UnsetCVar</code> let a string pick a priority or remove one, but they are compiled only under <code>#if ALLOW_OTHER_PLATFORM_CONFIG</code> (<code>ConsoleManager.cpp:2831</code>). That macro is <code>WITH_UNREAL_DEVELOPER_TOOLS</code>, and Test and Shipping targets do not build developer tools by default.</p>
<p>A runtime code path whose meaning depends on the build configuration cannot be verified in the editor.</p>
<h2 id="where-it-is-the-right-tool">Where it is the right tool</h2>
<p>The priority that makes the node harmful in runtime code is what a developer wants from a debug tool:</p>
<ul>
<li>debug menus and cheat panels, where overriding every layer is the point,</li>
<li><code>stat</code> overlays, visualizers, and profiling switches,</li>
<li>automation and functional tests that need to force a state,</li>
<li>Editor Utility Widgets and other editor-only tooling.</li>
</ul>
<p>In all of these the caller is the developer, so the console priority matches who is writing. The boundary is whether the call can reach a player. A debug widget that ends up in a Shipping build has every problem of runtime code, plus cheat CVars that stop working without an error.</p>
<h2 id="blueprint-only-projects">Blueprint-only projects</h2>
<p>The strongest counterargument is that, in a Blueprint-only project, the node is the only way to write an arbitrary CVar. The settings a player normally controls do not need it. <code>UGameUserSettings</code> exposes them to Blueprint with the engine&rsquo;s priorities behind them: <code>ApplySettings</code>, <code>SetFrameRateLimit</code>, <code>SetShadowQuality</code>, and the other quality setters are all <code>BlueprintCallable</code> (<code>Engine/Classes/GameFramework/GameUserSettings.h:49</code>, <code>:143</code>, <code>:186</code>).</p>
<p>A CVar that no engine system manages needs one small C++ function. The priority enum is not a <code>UENUM</code>, so a <code>BlueprintCallable</code> wrapper picks the priority and calls this:</p>
<div class="highlight" data-lang="cpp">
  <button type="button" class="code-copy" data-code-copy data-label="Copy" data-copied="Copied!" aria-label="Copy code to clipboard">Copy</button><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">bool</span> <span class="nf">SetCVarInt</span><span class="p">(</span><span class="k">const</span> <span class="n">TCHAR</span><span class="o">*</span> <span class="n">Name</span><span class="p">,</span> <span class="n">int32</span> <span class="n">Value</span><span class="p">,</span> <span class="n">EConsoleVariableFlags</span> <span class="n">SetBy</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">IConsoleVariable</span><span class="o">*</span> <span class="n">CVar</span> <span class="o">=</span> <span class="n">IConsoleManager</span><span class="o">::</span><span class="n">Get</span><span class="p">().</span><span class="n">FindConsoleVariable</span><span class="p">(</span><span class="n">Name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">CVar</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">CVar</span><span class="o">-&gt;</span><span class="n">Set</span><span class="p">(</span><span class="n">Value</span><span class="p">,</span> <span class="n">SetBy</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">CVar</span><span class="o">-&gt;</span><span class="n">GetFlags</span><span class="p">()</span> <span class="o">&amp;</span> <span class="n">ECVF_SetByMask</span><span class="p">)</span> <span class="o">==</span> <span class="n">SetBy</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p><code>Set</code> returns <code>void</code>, but a write that lands also stores its priority on the CVar (<code>ConsoleManager.cpp:320</code>), so reading the priority back tells the caller whether the write took effect. The function reports a missing CVar too, and it never goes through command routing, so no exec handler can disappear between PIE and Shipping.</p>
<h2 id="what-to-use-instead">What to use instead</h2>
<p>Each value of the priority enum carries a comment that names the code it is meant for (<code>IConsoleManager.h:144-175</code>), and each layer a shipped game needs has an owner that writes at its own level:</p>
<ul>
<li>the quality levels belong to the scalability system, which is exposed to Blueprint through <code>UGameUserSettings</code> (<code>Scalability</code>),</li>
<li>the player&rsquo;s own settings belong to <code>UGameUserSettings</code> (<code>GameSetting</code>),</li>
<li>project-wide defaults belong to Project Settings and the project&rsquo;s ini files (<code>ProjectSetting</code>, <code>SystemSettingsIni</code>),</li>
<li>per-platform values belong to device profiles (<code>DeviceProfile</code>).</li>
</ul>
<p>Project Settings and the ini files outrank the quality levels. A value that should differ per quality level belongs in the project&rsquo;s scalability ini, next to the engine&rsquo;s own sections such as <code>[ShadowQuality@0]</code>, and not in Project Settings or <code>[ConsoleVariables]</code>.</p>
<p><code>Console</code> is described as the priority used via the editor UI or the interactive console (<code>IConsoleManager.h:174</code>), which means a person at a keyboard. Runtime code should write at the priority whose description matches the caller, and the owners listed above already do.</p>
<div class="callout callout--tip">
  <div class="callout__title">Tip</div>
  To remove a console-priority override that a third-party plugin has applied, call <code>IConsoleVariable::Unset(ECVF_SetByConsole)</code> from C++. It removes one priority from the history and recomputes the value from what is left (<code>ConsoleManager.cpp:1172</code>, recompute at <code>:1200-1216</code>), and no build configuration guards it. In the case above the highest remaining entry is <code>Scalability</code>, so the value returns to whatever the quality level asks for. The plugin&rsquo;s next console command reapplies the override, so the lasting fix is in the plugin.
</div>

<h2 id="why-it-matters-most-in-plugins">Why it matters most in plugins</h2>
<p>In a game&rsquo;s own runtime graph, the node overrides the settings system the game itself depends on. In a plugin&rsquo;s runtime graph, it does that in every project that installs it, outranking settings, device profiles, and hotfixes its author has never seen. The trace it leaves in each of those projects is a warning line each time a lower layer is overruled, and a Shipping build does not print it. A plugin that needs a particular value should document it and let the project put it at the right layer. If it has to force one, it should expose a switch that turns the override off.</p>
]]></content:encoded>
      
    </item>
    
  </channel>
</rss>
