2

I'm importing data from an XML file. I'm having trouble accessing some of the deeper nodes in the xml file.

Example of my xml here (chapter being the repeating item):

<article xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en" class="techreport">

<chapter>
<title> Title – Version 5.0.11.110 </title>
<subtitle> Release Notes </subtitle>
<info>...</info>
<sect1>
<title> Improvement </title>
<sect2>
<title> AP - Accounts Payable </title>
<itemizedlist>
<listitem xml:id="A50-3451-1">
<para>
Allow edit for Shipment Comment on Both Shipments after Post Invoice if Edit Shipment After Posting is enabled.
</para>
</listitem>
<listitem xml:id="A50-3487-2">
<para>
Make AP Generate Payment form and report all fields from AP Transaction.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2>
<title> CB - Cash Book </title>
<itemizedlist>
<listitem xml:id="A50-3314-3">
<para>
Added StatementID, StatementLineNo and PeriodReconciled as available fields for the transactions band on the CB Unreconciled Transactions layout, making it easy to see if a transaction which is unreconciled as at the period reported on is on a statement, and reconciled subsequently.
</para>
</listitem>
</itemizedlist>
</sect2>
</sect1>
<sect1>
<title> Bug Fix </title>
<sect2>
<title> ALL - All Modules </title>
<itemizedlist>
<listitem xml:id="A50-3400-1">
<para>
Fix possible A record already exists with that Layout (..) code - Error message.
</para>
</listitem>
</itemizedlist>
</sect2>
</sect1>
</chapter>

</article>

And my template code so far:

{% set params0 = {
    url: 'https://sitename/downloads/ReleaseNotes.xml',
    type: 'xml',
    element: 'chapter',
    cache: 60,
} %}

{% set params1 = {
    url: 'https://sitename/downloads/ReleaseNotes.xml',
    type: 'xml',
    element: 'sect1',
    cache: 60,
} %}

{% set params2 = {
    url: 'https://sitename/downloads/ReleaseNotes.xml',
    type: 'xml',
    element: 'sect2',
    cache: 60,
} %}


{% set feed0 = craft.feedme.feed(params0) %}
{% set feed1 = craft.feedme.feed(params1) %}
{% set feed2 = craft.feedme.feed(params2) %}

{% for node in feed0 %}
    <h4><strong>{{ node.title }}</strong></h4>

    {% for node in feed1 %}
        <p>{{ node.title }}</p>

        {% for node in feed2 %}
            <p>{{ node.title }}</p>
            <p>{{ node.itemizedlist.listitem.para }}</p>
        {% endfor %}

    {% endfor %}

{% endfor %}

I've ended up using multiple feeds as I couldn't get to the "para" node at all. This maybe wrong. I thought that <p>{{ node.itemizedlist.listitem.para }}</p> would do the trick. Can someone offer some help please.

1
  • @KSP If you use this node.itemizedlist[0].listitem.para you will only get the first item :)
    – Dennisvdw
    Jun 9, 2020 at 13:22

2 Answers 2

1

I think your problem is that <listitem xml:id="A50-3487-2"> has an attribute, so you would need to use <p>{{ node.itemizedlist.listitem['@'].para }}</p> to get the node value.

See the bottom of the docs here: https://docs.craftcms.com/feed-me/v4/feature-tour/using-in-your-templates.html

2
  • Thanks, I tried that after finding those docs but I get a runtime error: Key "@" for array with keys "0, 1" does not exist. Still not sure what's going on
    – xenowebdev
    Feb 28, 2020 at 21:19
  • Ah! I think the issue rather is that you need to loop over the itemizedlist as it’s an array of listitems. So it’s for instance node.itemizedlist[0].listitem.para should probably work!
    – KSP
    Feb 29, 2020 at 13:10
0

Here's the final solution in case anyone else comes across this post. It is a specific use-case answer.

{% set feedParams = {
  url: 'https://yoursite.com/folder/ReleaseNotes.xml',
  type: 'xml',
  element: 'chapter',
  cache: 60,
} %}

{% set chapters = craft.feedme.feed(feedParams) %}

{% for chapter in chapters %}
  <h4 style="color:#0096dc;"><strong>{{ chapter.title }}</strong></h4>
  <hr>
  {% if chapter.sect1.title is defined %} {# There's only one sect1 within this chapter node #}
    {{ _self.level1(chapter.sect1) }}
  {% elseif chapter.sect1 is defined %}
    {% for sect in chapter.sect1 %}
      {{ _self.level1(sect) }}
      <p>&nbsp;</p>
    {% endfor %}
  {% endif %}
{% endfor %}


{% macro level1(section) %}
  <h5 style="margin-bottom:1rem;"><strong>{{ section.title }}</strong></h5>
  {% if section.sect2.title is defined %} {# There's only one sect2 within this sect1 node #}
    {{ _self.level2(section.sect2) }}
  {% elseif section.sect2 is defined %}
    {% for subsection in section.sect2 %}
      {{ _self.level2(subsection) }}
    {% endfor %}
  {% endif %}
{% endmacro %}


{% macro level2(subsection) %}
  <p style="color:;"><strong><i>{{ subsection.title }}</i></strong></p>
  {% if subsection.itemizedlist.listitem.para is defined %}
    {{ _self.level3(subsection.itemizedlist.listitem) }}
  {% elseif subsection.itemizedlist.listitem is defined %}
    {% for item in subsection.itemizedlist.listitem %}
      {{ _self.level3(item) }}
    {% endfor %}
  {% endif %}
{% endmacro %}


{% macro level3(item) %}
  <p style="padding-left:15px;">{{ item.para }}</p>
{% endmacro %}

Thanks to @KSP and to @Evan Warner on Craft Discord for the final answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.