Expand my Community achievements bar.

Guidelines for the Responsible Use of Generative AI in the Experience Cloud Community.
SOLVED

RSS feed creation for AEM website

Avatar

Level 5

We have requirement like ,Sites needs to provide a new feed for the external agencies to consume and display news on their portal.

Can you share any suggestions for how to create the RSS feeds.

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @Nandheswara ,
As being said, There is not OOTB feature available to export RSS/xml feed. You can't use OOTB headless as you are looking for xml output. Implementing custom solution is not difficult. Let me give you two solutions. 

1. Implement custom content exporter to export xml data. This is just Sling Model exporter but it export content in xml format instead json format. Instead of Jackson exporter you will be using your own custom Sling Model exporter. This is standard framework for implementing custom exporter. 

2. Write a custom Servlet/Service to get XML data. 

Solution 1 - Custom Sling Model Exporter 

   1- Create Class/backend Component by implementing ModelExporter 

   2- You must have 3 overridden methods.
           export() -  This method return your actual content. I am using JAXB api to export xml. You can implement          your own api as well.

         getName() - You will be using this name in your sling model. 

         isSupported() - class support exporter. 

   3. Now use this Model Exporter in Sling Model as 

@Exporter(name = "geeksxml",extensions = "xml",selector = "geeks")

 4. You have to use JAXB specific annotations in Sling Model as we do for OOTB Jackson exporter

@XmlRootElement
@XmlElementWrapper
@XmlElement

Sample code for Model Exporter

@Component(service = ModelExporter.class)
public class GeeksXmlExporter implements ModelExporter {
    private static final Logger LOG = LoggerFactory.getLogger(GeeksXmlExporter.class);
    @Override
    public boolean isSupported(Class<?> aClass) {
        return true;
    }

    @Override
    public <T> T export(Object model, Class<T> aClass, Map<String, String> options) throws ExportException {
        StringWriter stringWriter = new StringWriter();
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(model.getClass());
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(model, stringWriter);
        } catch (JAXBException e) {
            LOG.info("\n Marshell Error : {} ",e.getMessage());
        }
        return (T) stringWriter.toString();
    }

    @Override
    public String getName() {
        return "geeksxml";
    }
}

Sling Model code. In this I explained how to use xml exporter in Sling Model.

Exporter(name = "geeksxml",extensions = "xml",selector = "geeks")
@Model(
        adaptables = SlingHttpServletRequest.class,
        adapters = XmlExporter.class,
        resourceType = XmlExporterImpl.RESOURCE_TYPE,
        defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
@XmlRootElement(name = "geeks-exporter")
public class XmlExporterImpl implements XmlExporter {
    static final String RESOURCE_TYPE="aemgeeks/components/content/xmlexporter";
    private static final Logger LOG = LoggerFactory.getLogger(XmlExporterImpl.class);

    @Inject
    Resource componentResource;

    @ValueMapValue
    String xmltitle;

    @ValueMapValue
    String xmldescription;

    @ValueMapValue
    Calendar xmldate;

    @ValueMapValue
    private List<String> books;
    List<Map<String, String>> bookDetailsMap;
    @Override
    @XmlElement(name = "author-title")
    public String getTitle() {
        return xmltitle;
    }
    @Override
    @XmlElement(name = "author-description")
    public String getDescription() {
        return xmldescription;
    }
    @Override
    @XmlElementWrapper(name = "books")
    @XmlElement(name="book")
    public List<String> getBooks() {
        if (books != null) {
            return new ArrayList<String>(books);
        } else {
            return Collections.emptyList();
        }
    }
    @Override
    @XmlElement(name = "publish-date")
    public Calendar getDate() {
        return xmldate;
    }
    @XmlElement(name = "author-name")
    public String getAuthorName(){
        return "AEM GEEKS";
    }
}

You can get complete code and working demo here.
Exporter - https://github.com/aemgeeks1212/aemgeeks/blob/master/core/src/main/java/com/aem/geeks/core/exporter/...
Sling Model - https://github.com/aemgeeks1212/aemgeeks/blob/master/core/src/main/java/com/aem/geeks/core/models/im...

Video Tutorial - 

https://youtu.be/m3g7vnVlKCk

https://youtu.be/Vb2ajGUE4Oc

 

Solution 2 - Write Servlet/ Service. 
This is custom solution. You can write code to export xml as per your need. I am sharing servlet which export pages title and name in xml formate. This is just demo/sample code. You can implement in same way as per your need.

@Override
    protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) {

        try {
            DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
            Document document = documentBuilder.newDocument();

            ResourceResolver resourceResolver = ResolverUtil.newResolver(resourceResolverFactory);
            Page page = resourceResolver.adaptTo(PageManager.class).getPage("/content/aemgeeks/us/en");
            Iterator<Page> childPages = page.listChildren();
            Element root = document.createElement("allnews");
            document.appendChild(root);
            while (childPages.hasNext()) {
                Element news = document.createElement("news");
                root.appendChild(news);

                Page childPage = childPages.next();
                Element title = document.createElement("title");
                title.appendChild(document.createTextNode(childPage.getTitle()));
                news.appendChild(title);

                Element name = document.createElement("name");
                name.appendChild(document.createTextNode(childPage.getName()));
                news.appendChild(name);

            }
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource domSource = new DOMSource(document);
            resp.setContentType("application/xml");
            StreamResult streamResult = new StreamResult(resp.getWriter());
            transformer.transform(domSource,streamResult);

        } catch (Exception e) {
            LOG.info("\n ERROR GET - {} ", e.getMessage());
        }
    }

Complete code file here - https://github.com/aemgeeks1212/aemgeeks/blob/master/core/src/main/java/com/aem/geeks/core/servlets/...

 

I hope this will be helpful. It will help to implement your use case. 

View solution in original post

5 Replies

Avatar

Community Advisor

@Pallavi_Shukla_ The article which you shared is for pulling/consuming data from third party and displaying it in AEM. However original ask was for exporting from AEM.

@Nandheswara There isn't any OOTB functionality. You have to build your logic to do this by creating custom service/component.

Though, you can consider about AEM headless - endpoints and delivering its content as JSON.

For more details please check below 2 URL's:

  1. https://experienceleague.adobe.com/docs/experience-manager-learn/getting-started-with-aem-headless/o...
  2. https://www.specbee.com/blogs/introduction-headless-or-decoupled-cms-aem-6.5

Hope that helps you!

Regards,

Santosh

 

Avatar

Correct answer by
Community Advisor

Hi @Nandheswara ,
As being said, There is not OOTB feature available to export RSS/xml feed. You can't use OOTB headless as you are looking for xml output. Implementing custom solution is not difficult. Let me give you two solutions. 

1. Implement custom content exporter to export xml data. This is just Sling Model exporter but it export content in xml format instead json format. Instead of Jackson exporter you will be using your own custom Sling Model exporter. This is standard framework for implementing custom exporter. 

2. Write a custom Servlet/Service to get XML data. 

Solution 1 - Custom Sling Model Exporter 

   1- Create Class/backend Component by implementing ModelExporter 

   2- You must have 3 overridden methods.
           export() -  This method return your actual content. I am using JAXB api to export xml. You can implement          your own api as well.

         getName() - You will be using this name in your sling model. 

         isSupported() - class support exporter. 

   3. Now use this Model Exporter in Sling Model as 

@Exporter(name = "geeksxml",extensions = "xml",selector = "geeks")

 4. You have to use JAXB specific annotations in Sling Model as we do for OOTB Jackson exporter

@XmlRootElement
@XmlElementWrapper
@XmlElement

Sample code for Model Exporter

@Component(service = ModelExporter.class)
public class GeeksXmlExporter implements ModelExporter {
    private static final Logger LOG = LoggerFactory.getLogger(GeeksXmlExporter.class);
    @Override
    public boolean isSupported(Class<?> aClass) {
        return true;
    }

    @Override
    public <T> T export(Object model, Class<T> aClass, Map<String, String> options) throws ExportException {
        StringWriter stringWriter = new StringWriter();
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(model.getClass());
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(model, stringWriter);
        } catch (JAXBException e) {
            LOG.info("\n Marshell Error : {} ",e.getMessage());
        }
        return (T) stringWriter.toString();
    }

    @Override
    public String getName() {
        return "geeksxml";
    }
}

Sling Model code. In this I explained how to use xml exporter in Sling Model.

Exporter(name = "geeksxml",extensions = "xml",selector = "geeks")
@Model(
        adaptables = SlingHttpServletRequest.class,
        adapters = XmlExporter.class,
        resourceType = XmlExporterImpl.RESOURCE_TYPE,
        defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
@XmlRootElement(name = "geeks-exporter")
public class XmlExporterImpl implements XmlExporter {
    static final String RESOURCE_TYPE="aemgeeks/components/content/xmlexporter";
    private static final Logger LOG = LoggerFactory.getLogger(XmlExporterImpl.class);

    @Inject
    Resource componentResource;

    @ValueMapValue
    String xmltitle;

    @ValueMapValue
    String xmldescription;

    @ValueMapValue
    Calendar xmldate;

    @ValueMapValue
    private List<String> books;
    List<Map<String, String>> bookDetailsMap;
    @Override
    @XmlElement(name = "author-title")
    public String getTitle() {
        return xmltitle;
    }
    @Override
    @XmlElement(name = "author-description")
    public String getDescription() {
        return xmldescription;
    }
    @Override
    @XmlElementWrapper(name = "books")
    @XmlElement(name="book")
    public List<String> getBooks() {
        if (books != null) {
            return new ArrayList<String>(books);
        } else {
            return Collections.emptyList();
        }
    }
    @Override
    @XmlElement(name = "publish-date")
    public Calendar getDate() {
        return xmldate;
    }
    @XmlElement(name = "author-name")
    public String getAuthorName(){
        return "AEM GEEKS";
    }
}

You can get complete code and working demo here.
Exporter - https://github.com/aemgeeks1212/aemgeeks/blob/master/core/src/main/java/com/aem/geeks/core/exporter/...
Sling Model - https://github.com/aemgeeks1212/aemgeeks/blob/master/core/src/main/java/com/aem/geeks/core/models/im...

Video Tutorial - 

https://youtu.be/m3g7vnVlKCk

https://youtu.be/Vb2ajGUE4Oc

 

Solution 2 - Write Servlet/ Service. 
This is custom solution. You can write code to export xml as per your need. I am sharing servlet which export pages title and name in xml formate. This is just demo/sample code. You can implement in same way as per your need.

@Override
    protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) {

        try {
            DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
            Document document = documentBuilder.newDocument();

            ResourceResolver resourceResolver = ResolverUtil.newResolver(resourceResolverFactory);
            Page page = resourceResolver.adaptTo(PageManager.class).getPage("/content/aemgeeks/us/en");
            Iterator<Page> childPages = page.listChildren();
            Element root = document.createElement("allnews");
            document.appendChild(root);
            while (childPages.hasNext()) {
                Element news = document.createElement("news");
                root.appendChild(news);

                Page childPage = childPages.next();
                Element title = document.createElement("title");
                title.appendChild(document.createTextNode(childPage.getTitle()));
                news.appendChild(title);

                Element name = document.createElement("name");
                name.appendChild(document.createTextNode(childPage.getName()));
                news.appendChild(name);

            }
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource domSource = new DOMSource(document);
            resp.setContentType("application/xml");
            StreamResult streamResult = new StreamResult(resp.getWriter());
            transformer.transform(domSource,streamResult);

        } catch (Exception e) {
            LOG.info("\n ERROR GET - {} ", e.getMessage());
        }
    }

Complete code file here - https://github.com/aemgeeks1212/aemgeeks/blob/master/core/src/main/java/com/aem/geeks/core/servlets/...

 

I hope this will be helpful. It will help to implement your use case. 

Avatar

Level 5

This is for exporting the single component content i want to export entire page with component content.

how can i achieve exporting all component content in a page to xml? 

Avatar

Community Advisor

@Nandheswara I gave you two solution for both scnerios. You can try to use second one. Write a servlet and create your custom content and export in xml format as I explained in demo code.