Pergunta

Eu pretendo implementar Martin Fowler Padrão de visão em duas etapasPara renderizar o HTML em um aplicativo da web, estou escrevendo. A idéia geral é que, em vez de ter a saída de aplicativo em HTML bruto, ele gera um XML intermediário personalizado que é convertido em HTML/CSS. Isso possui várias vantagens, incluindo duplicação reduzida de código e uma saída mais consistente.

A abordagem sugerida por Fowler para converter o XML para o HTML final é usar o XSLT.

Eu já usei o XSLT antes e conheço o básico. No entanto, estou me perguntando quais são as vantagens de usar o XSLT. Uma abordagem alternativa que estou considerando se parece com o seguinte:

Aqui está um exemplo de saída XML da primeira etapa de renderização:

<grid>
   <headingRow>
      <cell>Product</cell>
      <cell>Price</cell>
   </headingRow>
   <row>
      <cell>A product</cell>
      <cell type="price">$54.95</cell>
   </row>
</grid>

E a saída HTML final desejada:

<table class="grid">
  <tr>
    <th>Product</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>A product</td>
    <td>
      <span class="currency_symbol">$</span>
      <span class="decimal_number">54.95</span>
    </td>
  </tr>
</table>

A abordagem que estou considerando teria um objeto para cada tag.

class GridTag extends Tag {
  ...
  public void render() {
    System.out.println("<table class=\"grid\">");
    foreach(Tag child: children) {
      child.render();
    }
    System.out.println("</table>");
  }
  ...
}

Os objetos seriam construídos em uma árvore analisando o XML. O método render () seria chamado no nó raiz. Gosto particularmente dessa abordagem porque me permite fazer coisas legais. Particularmente, se eu tiver uma tag de célula como acima com o atributo tipo = "Price":

<cell type="price">$54.95</price>

A classe de tags associada pode analisar o conteúdo da tag para separar o símbolo da moeda e o valor numérico em tags HTML separadas para permitir o alinhamento do símbolo da moeda e do ponto decimal, como na saída HTML acima.

<td>
  <span class="currency_symbol">$</span>
  <span class="decimal_number">54.95</span>
</td>

Perguntas:

Devo fazer isso ou devo usar o XSLT? Quais são as vantagens de usar o XSLT que eu posso perder? Se eu deveria usar o XSLT, como iria analisar o conteúdo do preço?

Foi útil?

Solução

Eu realmente não posso dizer muito sobre por que você deve ir com um ou outro.

Eu acho que depende enormemente dos detalhes técnicos do seu processo de renderização, se você deseja que isso aconteça no servidor ou no navegador, quão confortável você está com o XSLT ou, respectivamente, a alternativa ao XSLT.

Um ponto por XSLT é certamente que é praticamente impossível gerar saída XML que não é bem formada (não estou falando de válido). É fácil perder algo ao escrever cordas.

Em relação ao seu problema de análise: sem dúvida, a melhor maneira é ter dados e formatos separados no XML. O XSLT não é para análise, então não vejo por que seu XML não pode estar neste formato desde o início:

<cell type="price" symbol="$">54.95</cell>

No entanto, supondo que você não possa fazer nada a respeito, esse XSLT cuidaria disso.

<xsl:template match="cell[@type='price']">
  <td>
    <xsl:variable name="vNonNumbers" select="translate(., '0123456789.', '')" />
    <xsl:variable name="vTheNumbers" select="translate(., $vNonNumbers, '')" />
    <span class="currency_symbol">
      <xsl:value-of select="$vNonNumbers" />
    </span>
    <span class="decimal_number">
      <xsl:value-of select="$vTheNumbers" />
    </span>
  </td>
</xsl:template>

Espero que você possa ver por que o acima é essencialmente ruim código. Compare com a alternativa (se o seu xml gostaria dados e formato separados):

<xsl:template match="cell[@type='price']">
  <td>
    <span class="currency_symbol">
      <xsl:value-of select="@symbol" />
    </span>
    <span class="decimal_number">
      <xsl:value-of select="." />
    </span>
  </td>
</xsl:template>

Outras dicas

O código que você está propondo tem alguns problemas. O maior é que você está codificando sua saída para o padrão, o que torna mais difícil fazer pós -processamento adicional. Isso não seria difícil mudar modificando seu método de renderização para aceitar um fluxo de saída ou escritor.

Independentemente disso, o que você está propondo é uma tonelada de código Java, que basicamente implementará uma transformação XSLT muito específica. Você está muito melhor apenas aprendendo e usando o XSLT para transformar o XML em HTML. A vantagem é que o XSLT é uma ferramenta de uso geral projetada para exatamente esse tipo de transformação.

Aqui está um exemplo de XSLT que quase faz o que você está tentando fazer. Infelizmente, fiquei sem Cuidados Bem na época em que tive que analisar o valor da moeda nas partes numéricas e simbólicas, mas isso certamente é suficiente para você começar.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="/grid">
    <table class="grid">
      <xsl:apply-templates select="headingRow"/>
      <xsl:apply-templates select="row"/>
    </table>
  </xsl:template>
  <xsl:template match="headingRow">
      <tr>
        <xsl:apply-templates select="cell" mode="heading"/>
      </tr>
  </xsl:template>
  <xsl:template match="row">
      <tr>
        <xsl:apply-templates select="cell" mode="normal"/>
      </tr>
  </xsl:template>  
  <xsl:template match="cell" mode="heading">
    <th><xsl:value-of select="."/></th>
  </xsl:template>

  <xsl:template match="cell" mode="normal">
    <xsl:choose>
      <xsl:when test="@type='price'">
        <td>
          <span class="currency_symbol">
            <xsl:value-of select="." />
          </span>
          <span class="decimal_number">
            <xsl:value-of select="." />
          </span>
        </td>
      </xsl:when>
      <xsl:otherwise>
        <td>
          <xsl:value-of select="." />
        </td>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top