2009-05-06 30 views
5

Comment écrire une fonction qui peut couper une chaîne avec des balises HTML en une chaîne de longueur N sans casser les balises HTML tout en le faisant.Découper des chaînes HTML sans casser les balises HTML

La chaîne retournée n'a pas besoin d'avoir exactement N caractères. Il peut le couper avant ou après le tag qui est sur le bord de la chaîne N-long.

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

CutIt(9) devrait retourner

Visit 

ou

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

Répondre

2

je résolu le problème est ici le code donc 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

Cela peut échouer lorsque les balises de commentaire "" ne compteront pas correctement la balise de fermeture. –

+0

Ceci est la suppression des balises html .. –

0

Quand je rencontrais ce problème (pour les flux RSS) Je viens d'appeler strip_tags avant de couper ma chaîne.

1

Cela peut être exagéré, mais essayez de rechercher AWK, il peut faire ce genre de choses assez facilement car il est centré sur le traitement du texte.

Vous pouvez également écrire un script d'analyse syntaxique personnalisé comme

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 

... ou quelque chose comme ça (n'ont pas testé, mais il vous donne l'idée).

EDIT: Vous aussi ajouter quelque chose à détecter si l'étiquette est fermée ou non (il suffit d'ajouter un drapeau comme in_tag et le mélanger avec une expression régulière et il devrait fonctionner) espoir qui aide

EDIT2: si vous avez indiqué la langue que vous voulez utiliser, cela pourrait être utile. javascript?

+0

..je préfère C#, mais le pseudo code est ok aussi – Ante

+0

cool, parce que je ne sais pas vraiment C# ^^ – marcgg

0

En javascript, vous pouvez utiliser la propriété textContent des éléments DOM pour l'obtenir.

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

Je dois noter que si nous voulons couper la chaîne sur la balise, elle le coupera avant " avant qu'il reste ouvert. C'est le cas que nous voulons éviter! – 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; 
} 


utilisation

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

c'est une bonne réponse et de travail – Arthur

Questions connexes