2009-05-06 16 views
5

Jak napisać funkcję, która może wyciąć ciąg znaków HTML do ciągu N-długości bez łamania znaczników HTML podczas tego.Wycinanie ciągów HTML bez łamania znaczników HTML

Zwrócony ciąg nie musi mieć dokładnie N znaków. Może wyciąć go przed lub po znaczniku znajdującym się na krawędzi długiego łańcucha.

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

CutIt(9) powinien powrócić

Visit 

lub

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

Odpowiedz

2

I rozwiązać problem tak oto kod w 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

To może się nie udać, gdy mają znaczniki komentarza '' nie będzie poprawnie liczył znacznika zamykającego. –

+0

To jest usuwanie tagów html .. –

0

Kiedy spotkałem takiego problemu (RSS) Właśnie zwane strip_tags przed cięciem mój łańcuch.

1

To może być przesada, ale spróbuj wyszukać AWK, może to zrobić całkiem łatwo, ponieważ koncentruje się na przetwarzaniu tekstu.

Można również napisać skrypt niestandardowy parsowania jak

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 

... czy coś takiego (nie testowałem, ale daje pomysł).

EDIT: Będziesz mieć również dodać coś wykryć, czy tag jest zamknięty lub nie (wystarczy dodać flagę jak in_tag i wymieszać ją z jakiegoś wyrażenia regularnego i powinno działać) nadzieję, że pomoże

EDIT2: jeśli podałeś język, którego chcesz użyć, może to być pomocne. javascript?

+0

..ja wolę C#, ale pseudo kod też jest w porządku – Ante

+0

fajnie, bo tak naprawdę nie wiem C# ^^ – marcgg

0

W javascript można użyć właściwości textContent elementów DOM w celu uzyskania tego.

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

Musisz zauważyć, że jeśli chcemy wyciąć napis na tagu to wycina go przed ", zanim pozostanie otwarty. Tak właśnie chcemy zapobiec! – 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; 
} 


Wykorzystanie

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

to jest dobra i działająca odpowiedź – Arthur

Powiązane problemy