2009-05-06 22 views
5

Cómo escribir una función que puede cortar una cadena con etiquetas HTML en una cadena de longitud N sin romper las etiquetas HTML mientras lo hace.Cortar cadenas HTML sin romper etiquetas HTML

La cadena devuelta no necesita tener exactamente N caracteres de longitud. Puede cortarlo antes o después de la etiqueta que está en el borde de la cadena N larga.

Visit <a href="www.htz.hr">Croatia</a> this summer. 

CutIt(9) deberían volver

Visit 

o

Visit <a href="www.htz.hr">Croatia</a> 

Respuesta

2

He resuelto el problema por lo que aquí está el código en C#;

static string CutIt(string s, int limit) 
{ 
    if (s.Length < limit) return s; 

    int okIndex = 0; 
    bool inClosingTag = false; 
    int numOpenTags = 0; 

    for (int i = 0; i < limit; i++) 
    { 
     if (s[i]=='<') 
     { 
      if (s[i+1]=='/') 
      { 
       inClosingTag = true;  
      } 
      else 
      { 
       numOpenTags++; 
      } 
     } 
     if (s[i]=='>') 
     { 
      if (s[i-1]=='/') 
      { 
       numOpenTags--; 
      } 
      if (inClosingTag) 
      { 
       numOpenTags--; 
      } 
     } 

     if (numOpenTags == 0) okIndex = i; 

    } 
    return s.Substring(0, okIndex + 1); 
} 
+1

Esto puede fallar cuando se tienen etiquetas de comentarios '' no contará la etiqueta de cierre correctamente. –

+0

Esto quita etiquetas html .. –

0

Cuando me encontré con ese problema (por RSS) acabo de llamar a strip_tags antes de cortar mi cadena.

1

Esto puede ser exagerado, pero intente buscar AWK, puede hacer este tipo de cosas con bastante facilidad, ya que se centra en el procesamiento de texto.

También puede escribir un guión de análisis personalizada como

string s = "Visit <a href="www.htz.hr">Croatia</a> this summer." 

result = "" 

slice_limit = 9 

i= 0 

j = 0 

in_tag = false 

while i < slice_limit and j < s.size do 

    if s[j] == "<" then in_tag = true 

    if in_tag and s[i]==">" then in_tag = false 

    if !in_tag then i++ 

    result += s[j] 

end 

... o algo por el estilo (no hemos probado, pero te da la idea).

EDITAR: También tendrá que añadir algo para detectar si la etiqueta está cerrado o no (sólo tiene que añadir una bandera como in_tag y mezclar con un poco de expresión regular y debería funcionar) Espero que ayude

EDIT2: si proporcionó el idioma que desea utilizar, podría ser útil. javascript?

+0

..prefiero C#, pero el pseudo código también está bien – Ante

+0

genial, porque realmente no sé C# ^^ – marcgg

0

En javascript, puede usar la propiedad textContent de elementos DOM para obtener esto.

HTML

<p id='mytext'>Hey <a href="#">Visit Croatia</a> today</p> 

Javascript

var el = document.getElementById("mytext"); 
console.log(el.textContent); 
//alert(el.textContent); // if you don't have firebug. 
1
static string CutIt(string s, int limit) 
{ 
    s = s.Substring(0, limit); 
    int openMark = s.LastIndexOf('<'); 
    if (openMark != -1) 
    { 
    int closeMark = s.LastIndexOf('>'); 
    if (openMark > closeMark) 
    { 
     s = s.Substring(0, openMark); 
    } 
    } 
    return s.Trim(); 
} 

public static void Main() 
{ 
    Console.WriteLine(
    CutIt("Visit <a href=\"www.htz.hr\">Croatia</a> this summer.", 9) 
); // prints "Visit" 
} 
+0

U hay que notar que si queremos cortar la cadena en la etiqueta, cortará antes de " etiqueta antes de que permanezca abierta. ¡Ese es el caso que queremos evitar! – Ante

4
function trimHtml(html, options) { 

    options = options || {}; 

    var limit = options.limit || 100, 
     preserveTags = (typeof options.preserveTags !== 'undefined') ? options.preserveTags : true, 
     wordBreak = (typeof options.wordBreak !== 'undefined') ? options.wordBreak : false, 
     suffix = options.suffix || '...', 
     moreLink = options.moreLink || ''; 

    var arr = html.replace(/</g, "\n<") 
     .replace(/>/g, ">\n") 
     .replace(/\n\n/g, "\n") 
     .replace(/^\n/g, "") 
     .replace(/\n$/g, "") 
     .split("\n"); 

    var sum = 0, 
     row, cut, add, 
     tagMatch, 
     tagName, 
     tagStack = [], 
     more = false; 

    for (var i = 0; i < arr.length; i++) { 

     row = arr[i]; 
     // count multiple spaces as one character 
     rowCut = row.replace(/[ ]+/g, ' '); 

     if (!row.length) { 
      continue; 
     } 

     if (row[0] !== "<") { 

      if (sum >= limit) { 
       row = ""; 
      } else if ((sum + rowCut.length) >= limit) { 

       cut = limit - sum; 

       if (row[cut - 1] === ' ') { 
        while(cut){ 
         cut -= 1; 
         if(row[cut - 1] !== ' '){ 
          break; 
         } 
        } 
       } else { 

        add = row.substring(cut).split('').indexOf(' '); 

        // break on halh of word 
        if(!wordBreak) { 
         if (add !== -1) { 
          cut += add; 
         } else { 
          cut = row.length; 
         } 
        } 
       } 

       row = row.substring(0, cut) + suffix; 

       if (moreLink) { 
        row += '<a href="' + moreLink + '" style="display:inline">»</a>'; 
       } 

       sum = limit; 
       more = true; 
      } else { 
       sum += rowCut.length; 
      } 
     } else if (!preserveTags) { 
      row = ''; 
     } else if (sum >= limit) { 

      tagMatch = row.match(/[a-zA-Z]+/); 
      tagName = tagMatch ? tagMatch[0] : ''; 

      if (tagName) { 
       if (row.substring(0, 2) !== '</') { 

        tagStack.push(tagName); 
        row = ''; 
       } else { 

        while (tagStack[tagStack.length - 1] !== tagName && tagStack.length) { 
         tagStack.pop(); 
        } 

        if (tagStack.length) { 
         row = ''; 
        } 

        tagStack.pop(); 
       } 
      } else { 
       row = ''; 
      } 
     } 

     arr[i] = row; 
    } 

    return { 
     html: arr.join("\n").replace(/\n/g, ""), 
     more: more 
    }; 
} 

if (typeof module !== 'undefined' && module.exports) { 
    module.exports = trimHtml; 
} 


uso

var html = '<div><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p><p>Ut 
enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip 
ex ea commodo consequat. </p><p>Duis aute irure dolor in reprehenderit in 
voluptate velit esse cillum dolore eu fugiat nulla pariatur. </p><p>Excepteur 
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit 
anim id est laborum.</p></div>'; 
var trim = trimHtml(html, { limit: 200 }); 


// **returns object** 


{ 
    html: '<div><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, 
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p><p>Ut 
    enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut... 
    </p></div>', 
    more: true // indicates if limit is reached 
} 

WORKING EXAMPLE

+1

es una respuesta buena y funcional – Arthur