Umbraco: Guardar dataypes complexos e navegar pelos parâmetros destes usando xslt

Para os que têm pressa, o que quero partilhar é que é possível guardar os dados de um DataType como XML e navegar pelas propriedades usando XPATH. Quem prefere usar UserControls talvez não sinta falta disto.

As vantagens que vejo nesta abordagem é que não precisamos de usar splits sobre os valores dos dataTypes, tanto em .Net como em XSLT, que para mais do que dois campos podem induzir em erros.

 

A história completa é assim:

Era uma vez um dataType do Umbraco chamado RelatedLinks, que permite adicionar links para conteúdos ou URLs:

RelatedLinkdatatype thumb1 Umbraco: Guardar dataypes complexos e navegar pelos parâmetros destes usando xslt

Certo dia este DataType deixou de mostrar a informação guardada na árvore dos nós do site (ainda não resolvi este mistério) então criei o meu controlo. Não tão sofisticado, mas faz o que quero.

clip image0025 thumb1 Umbraco: Guardar dataypes complexos e navegar pelos parâmetros destes usando xslt

Em vez de guardar os dados como string separada por | ou , ou ; queria ter um objecto que representasse o estado deste controlo em XML e guardá-lo na BD usando serialização de Xml.

E até aqui tudo bem. Usei o XMLSerializer e o Robbe D. Morri neste artigo, http://www.eggheadcafe.com/articles/xmlserializer_bulkload.asp, deu um toque ao relembrar que não precisamos de guardar os cabeçalhos de xml gerados por esta classe, visto que vamos encapsulá-los no xml do umbraco.

 

public partial class LinkPicker : System.Web.UI.UserControl, IUsercontrolDataEditor

{

       public class LinkPickerState

        {

            public string Title { get; set; }

            public string Url { get; set; }

            public string ContentId { get; set; }

            public string SelectedOption { get; set; }

        }

   /// <summary>

        /// Gets or sets the value.

        /// </summary>

        /// <value>The value.</value>

        public object value

        {

            get

            {

                LinkPickerState lps = new LinkPickerState() { Title = txtTitle.Text, Url = txtUrl.Text, SelectedOption = rblLinkUsed.SelectedValue, lps.ContentId = cpContentId.Text };  

                StringWriter Output = new StringWriter(new StringBuilder());

                new XmlSerializer(typeof(LinkPickerState)).Serialize(Output,lps);  

                //Cut down extra parameters (Credits to: http://www.eggheadcafe.com/articles/xmlserializer_bulkload.asp )   

                String ret = Output.ToString().Replace("xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"","");

                ret = ret.Replace("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"","");

                ret = ret.Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>","").Trim();

                ret = ret.Replace(Environment.NewLine,"");                

                return ret;

            }

            set

            {

                string _raw = value as string;

                if (!string.IsNullOrEmpty(_raw))

                {

                    StringReader sr = new StringReader(_raw);  

                    LinkPickerState lps = (LinkPickerState)new XmlSerializer(typeof(LinkPickerState)).Deserialize(sr);  

                    txtTitle.Text = lps.Title;

                    txtUrl.Text = lps.Url;

                    cpContentId.Text = lps.ContentId;

                    rblLinkUsed.SelectedValue = lps.SelectedOption;

                }

            }

        }

}

   

E na árvore de nós do umbraco apareceu assim:

 

<node id="1255" level="4" nodeName="Link 1" urlName="link-1" nodeTypeAlias="relatedLink">

<data alias="url"><![CDATA[asdsa]]></data>

          <data alias="text"><![CDATA[ads]]></data>

<data alias="link"><![CDATA[<LinkPickerState  >

  <Title />

  <Url />

  <ContentId />

  <SelectedOption>url</SelectedOption>

</LinkPickerState>]]></data>

</node>

O próximo problema era como converter esta string de dados em XML navegável.

O Google dizia para usar o node-set, uma extensão do XSLT que converte string em XML, mas comigo não funcionou. Por isso procurei como fazer isto em código, mas não estando familiarizado com XPATH em .net ia demorar algum tempo. Felizmente para mim, já alguém o tinha feito (fiz algumas alterações ao original):

http://forum.umbraco.org/yaf_postst5730_Parsing-a-string-as-XML-using-XSLT.aspx (No fim)

public XPathNodeIterator ParseToXML(string data){

      if (string.IsNullOrEmpty(data)){

                data = @"<Empty />”;

            }  

            StringReader stringReader = new StringReader(data);

            XPathDocument xPathDocument = new XPathDocument(stringReader);

            XPathNavigator xPathNavigator = xPathDocument.CreateNavigator();

            XPathExpression xPathExpression = xPathNavigator.Compile("/"); 

            XPathNodeIterator xPathNodeIterator = xPathNavigator.Select(xPathExpression); 

            return xPathNodeIterator;

        }

Adicionei este método às extensões que estou a usar e assim consigo a partir disto:

...
<![CDATA[<LinkPickerState  >
  <Title />
  <Url />
  <ContentId />
  <SelectedOption>url</SelectedOption>
</LinkPickerState>]]>
 

obter xml válido, fazendo assim:

<xsl:variable name="linkParameters" select="XsltExtensions:ParseToXml(string($relatedLink/data[@alias='link']))/LinkPickerState" />

clip image006 thumb1 Umbraco: Guardar dataypes complexos e navegar pelos parâmetros destes usando xslt

E fiquei feliz icon smile Umbraco: Guardar dataypes complexos e navegar pelos parâmetros destes usando xslt Podem ver que a seguir é possível navegar como se fosse um xml normal.

Para quem usa mais XSLT esta abordagem podem simplificar o processo em XPATH para além de podermos a nível de código estruturar melhor o estado do nosso datatype e introduzir-lhe funcionalidades adicionais.

 

Code long and prosper

autor: gustavo.castelo

Tags:

Leave a Reply

*


Better Tag Cloud