SDL Tridion: Logical structure of a page in XML format
Asked Answered
M

2

5

Is it possible to extract information of a SDL Tridion page including the contents associated to it in a xml format.

I am expecting something similar to this:

   <page name="mypagename">
     <page id="xxxxx"/>
     <template name="abc" id="123">
        <container name="xyz">
          <content name="asd" id="123">
           <Path="" \>
          </content>
        </container>
     </template>
    </page>

The technology stack is Tridion 2011 and Java.

I am a newbie to Tridion, so little detailed answer would be greatly helpful.

Medieval answered 6/3, 2013 at 1:21 Comment(1)
Please add which version of SDL Tridion you are using, and what technologies/languages you want to use.Lombardo
L
6

Depending what you actually need, there are MUCH simpler ways of doing this, but I use the following TBB class written in C# build a page XML divided into Content Regions based on Component Template Metadata

class GetPageXML : TemplateBase
    {
        public override void Transform(Engine engine, Package package)
        {
            Initialize(engine, package);
            Logger.Debug("This will get the full page XML");
            Item pageItem = m_Package.GetByType(ContentType.Page);

            Page currentPage = GetPage();

            m_Engine.PublishingContext.RenderContext.ContextVariables.Add("CURRENT_PAGE", currentPage);


            XmlDocument pageXml = pageItem.GetAsXmlDocument();
            foreach (XmlNode cpNode in pageXml.SelectNodes("/tcm:Page/tcm:Data/tcm:ComponentPresentations/tcm:ComponentPresentation", NSManager))
            {
                TcmUri componentURI = new TcmUri(cpNode.SelectSingleNode("tcm:Component/@xlink:href", NSManager).Value);
                TcmUri componentTemplateURI = new TcmUri(cpNode.SelectSingleNode("tcm:ComponentTemplate/@xlink:href", NSManager).Value);

                //Render the componentPresentation
                XmlNode cpRenderElement = pageXml.CreateElement("tcm", "RenderedComponentPresentation", "http://www.tridion.com/ContentManager/5.0");
                XmlAttribute attNamespace = pageXml.CreateAttribute("xmlns:tcdl");
                attNamespace.Value = "http://www.tridion.com/ContentDelivery/5.3/TCDL";
                cpRenderElement.Attributes.Append(attNamespace);


                if (m_Engine.PublishingContext.RenderContext.ContextVariables.Contains("ORDINAL_POSITION"))
                {
                    int ordinalPosition = ((int)m_Engine.PublishingContext.RenderContext.ContextVariables["ORDINAL_POSITION"]) + 1;
                    m_Engine.PublishingContext.RenderContext.ContextVariables["ORDINAL_POSITION"] = ordinalPosition;
                //    m_Engine.PublishingContext.RenderContext.ContextVariables["ORDINAL_POSITION"] = 0;
                }
                else
                {
                    m_Engine.PublishingContext.RenderContext.ContextVariables.Add("ORDINAL_POSITION", 0);
                }


                //Get the metadata from the CT
                ComponentTemplate componentTemplate = (ComponentTemplate)m_Engine.GetObject(componentTemplateURI);
                String metadataXmlString = "";
                String cpRegionName = "";
                if (componentTemplate.Metadata != null)
                {
                    metadataXmlString = componentTemplate.Metadata.OuterXml;
                    XmlNode cpRegionNode = componentTemplate.Metadata.SelectSingleNode("//*[local-name()='region']");
                    if (cpRegionNode != null)
                    {
                        cpRegionName = "_" + cpRegionNode.InnerText;
                    }
                }
                cpNode.SelectSingleNode("tcm:ComponentTemplate", NSManager).InnerXml = metadataXmlString;



                String REGIONAL_POSITION = "REGIONAL_POSITION" + cpRegionName;
                if (m_Engine.PublishingContext.RenderContext.ContextVariables.Contains(REGIONAL_POSITION))
                {
                    int regionalPosition = ((int)m_Engine.PublishingContext.RenderContext.ContextVariables[REGIONAL_POSITION]) + 1;
                    m_Engine.PublishingContext.RenderContext.ContextVariables[REGIONAL_POSITION] = regionalPosition;
                    //    m_Engine.PublishingContext.RenderContext.ContextVariables["ORDINAL_POSITION"] = 0;
                }
                else
                {
                    m_Engine.PublishingContext.RenderContext.ContextVariables.Add(REGIONAL_POSITION, 0);
                }



                DateTime cpRenderStart = DateTime.Now;
                string contentCP = m_Engine.RenderComponentPresentation(componentURI, componentTemplateURI);

                DateTime cpRenderEnd = DateTime.Now;
                TimeSpan cpRenderTime = cpRenderEnd.Subtract(cpRenderStart);

                XmlAttribute attCPRenderTime = pageXml.CreateAttribute("RenderTime");
                attCPRenderTime.Value = String.Format("{0:0000}", cpRenderTime.TotalMilliseconds) + " milliseconds";
                cpNode.Attributes.Append(attCPRenderTime);


                if (m_Engine.RenderMode != RenderMode.Publish)
                {
                    //Remove the '&' symbols created for linking in previewmode
                    contentCP = contentCP.Replace("&", "");

                }

                try
                {
                    cpRenderElement.InnerXml = contentCP;
                }
                catch (Exception e)
                {
                    cpRenderElement.InnerXml = "Malformed XML in the output:" + e.Message;// +"<!--" + contentCP + "-->";
                }
                cpNode.AppendChild(cpRenderElement);



                Component component = (Component)m_Engine.GetObject(componentURI);
                XmlAttribute attComponentRevisionDate = pageXml.CreateAttribute("ModifiedOn");
                attComponentRevisionDate.Value = component.RevisionDate.ToString("yyyy-MM-dd HH:mm:ss tt");
                cpNode.Attributes.Append(attComponentRevisionDate);



                //Get the metadata from the Component

                metadataXmlString = "";
                if (component.Metadata != null)
                {
                    metadataXmlString = component.Metadata.OuterXml;
                }

                cpNode.SelectSingleNode("tcm:Component", NSManager).InnerXml = metadataXmlString;
            }



            //Add the rendered/published time
            XmlAttribute attRenderTime = pageXml.CreateAttribute("RenderedAt");
            attRenderTime.Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss tt");
            pageXml.DocumentElement.Attributes.Append(attRenderTime);

            //Add PublishInfo
            //Get the PublishTransaction

            PublishTransaction pubTrans = GetPublishTransaction(engine);

            if (pubTrans != null)
            {
                XmlElement nodePublisher = pageXml.CreateElement("Publisher");
                XmlElement nodePublisherName = pageXml.CreateElement("name");
                XmlElement nodePublisherId = pageXml.CreateElement("id");
                XmlElement nodePublisherDescription = pageXml.CreateElement("description");

                nodePublisherName.InnerText = pubTrans.Creator.Title;
                nodePublisher.AppendChild(nodePublisherName);

                nodePublisherId.InnerText = pubTrans.Creator.Id.ToString();
                nodePublisher.AppendChild(nodePublisherId);

                nodePublisherDescription.InnerText = pubTrans.Creator.Description;
                nodePublisher.AppendChild(nodePublisherDescription);

                pageXml.DocumentElement.AppendChild(nodePublisher);
            }

            //Add the target info
            if (engine.PublishingContext.PublicationTarget != null)
            {
                XmlElement nodePublicationTarget = engine.PublishingContext.PublicationTarget.ToXml();
                XmlNode nodePubs = nodePublicationTarget.SelectSingleNode("/tcm:PublicationTarget/tcm:Data/tcm:Publications", NSManager);
                nodePubs.ParentNode.RemoveChild(nodePubs);


                pageXml.DocumentElement.AppendChild(pageXml.ImportNode(nodePublicationTarget, true));
            }





            //Add the Page Modified time
            ModificationInfo modInfo = GetNewestModificationDateFromPageXml(pageXml);

            XmlAttribute attContentModifiedTime = pageXml.CreateAttribute("ContentLastModifiedOn");
            attContentModifiedTime.Value = modInfo.ModificationDate.ToString("yyyy-MM-dd HH:mm:ss tt");
            pageXml.DocumentElement.Attributes.Append(attContentModifiedTime);

            XmlAttribute attLastModifiedItem = pageXml.CreateAttribute("LastModifiedItemURI");
            attLastModifiedItem.Value = modInfo.ItemURI.ToString();
            pageXml.DocumentElement.Attributes.Append(attLastModifiedItem);

            XmlAttribute attLastModifiedTitle = pageXml.CreateAttribute("LastModifiedItemTitle");
            attLastModifiedTitle.Value = modInfo.ItemTitle;
            pageXml.DocumentElement.Attributes.Append(attLastModifiedTitle);




            //Add PageTemplate Properties
            XmlNode nodePageTemplate = pageXml.SelectSingleNode("/tcm:Page/tcm:Data/tcm:PageTemplate", NSManager);
            TcmUri uriPageTemplate = new TcmUri(nodePageTemplate.Attributes["href", "http://www.w3.org/1999/xlink"].Value);
            XmlElement pageTemplateXml = engine.GetObject(uriPageTemplate).ToXml(XmlSections.Data);
            nodePageTemplate.ParentNode.ReplaceChild(pageXml.ImportNode(pageTemplateXml, true), nodePageTemplate);

            //Add the publication properties
            XmlNode nodePublication = pageXml.SelectSingleNode("/tcm:Page/tcm:Context/tcm:Publication", NSManager);
            TcmUri uriPublication = new TcmUri(nodePublication.Attributes["href", "http://www.w3.org/1999/xlink"].Value);
            XmlElement publicationXml = engine.GetObject(uriPublication).ToXml(XmlSections.Data);
            nodePublication.ParentNode.ReplaceChild(pageXml.ImportNode(publicationXml,true), nodePublication);
            m_Package.PushItem("UrbanCherryPageFrameWork", m_Package.CreateXmlDocumentItem(ContentType.Xml,pageXml));
        }

You could stop at the line XmlDocument pageXml = pageItem.GetAsXmlDocument();and simply push that value into the package and call it Output.

Alternatively take a look at the DD4T templates, as they output a standard XML structure for pages also.

Lombardo answered 6/3, 2013 at 5:18 Comment(8)
Is there a sample output you can provide? I am not a C# guy. Thanks for your time and a much detailed answer.Medieval
What technology do you want to use. It may be possile to do this with almost 100% XSLT, but you will need a least a little C# somewhere in your solutionLombardo
I am planning for a Java based solution.Medieval
You plan to write CM templates with Java? or are you trying to render pages on the delivery side with Java?Lombardo
@PrasannaKarthik - Any able and competent Java programmer should be able to write Tridion templates in C#. It's possible to use Java to generate .NET Tridion templates, but I can't imagine a scenario where this would be a good idea.Neukam
are you using the "un-supported" java mediator?Lombardo
Yes, we are planning to use Java mediator.Medieval
Thanks Chris, I got a very good overall idea on how Tridion would work based on your replies. This should help me in proceeding further. Once again thanks for your time and support.!!Medieval
C
4

You're actually asking for a quite difficult thing to answer, because of Tridion's flexible data model.

There's a few things known for sure:

  • There are Pages
    • Pages have properties like Title, ID, URL, Publication Id, Version, Creation Date, Published Date, etc
  • Pages may have Component Presentations
    • Component Presentations have content in them

The content of a component (or set of components) is most likely what you are searching for, since this is the data you want to display on your website. Components are stored as XML in the Tridion Content Manager, and transformed by a template when publishing. The XML schema that the component uses is defined by the implementer (therefore all implementations are likely to use different schemas) and the template that transforms that component is also defined by the implementer - and therefore all implementations are likely to have different outputs.

So, if you want to use Tridion XML to build up a website on the delivery tier, you need to:

  1. Define the schemas for your content according to your website requirements
  2. Define a template that will publish your content as XML to the delivery tier

(I am simplifying a lot here - don't underestimate the work required in defining a proper content model for any given organization)

Chris gives you a good example on how to push XML to the delivery tier. Frameworks like DD4T give you this template "for free" - but you still need to design the schemas yourself.

Cohere answered 6/3, 2013 at 14:14 Comment(3)
Pages have component presentations and components in turn have contents mapped to it. So the relation between page and content is through component. So my requirement is, if i publish the page; it should create an XML in the above structure containing the details of the component like styles to used, content mapped to it etc. Is that achievable? Thanks for your valuable time and answer..Medieval
The template provided by Chris will achieve that. Ask someone that has some Tridion experience (maybe from your client?) to put it in a Tridion template.Cohere
I want to know if this is achievable before talking to Clients, Hope you understand the situation.Medieval

© 2022 - 2024 — McMap. All rights reserved.