dAEkMedlem sedan feb. 20041 816 inlägg Gomorron,
Probemet jag kört fast vid är att jag har ett par HTML-dokument där attributen inte alltid omsluts av dubbelfnuttar. För det mesta finns de där men ibland är det enkelfnuttar istället och ibland inga fnuttar alls. Iaf, nu vill jag ha det som så att alla attributvärden omsluts av dubbelfnuttar - frågan är bara hur jag går till väga. Antar att det är regexp som gäller?
Innan jag går vidare och faktiskt ber om hjälp tänkte jag fråga om det finns nåt bra sätt att konvertera HTML till ett org.w3c.dom.Document-objekt? Fördelen med DOM är att det finns så himla bra metoder att använda sig av, och xpath.
Just nu läser jag in filerna från en remote disk och lagrar datan i en String/StringBuffer. Sedan ersätts de knasigheter jag ser med blotta ögat mha .replaceAll("apa", "banan"); och sedan är det inge problem att skapa ett Document-objekt av det hela. Fram tills nu vill säga. ;)
Fast det känns lite som att det borde finnas bättre sätt för det här är ju inte direkt smidigt...
LimeMedlem sedan sep. 2001961 inlägg Ja, du ska kunna parsa in ett HTML-träd i en DOM-träd, eftersom HTML ska vara well-formed.
dAEkMedlem sedan feb. 20041 816 inlägg Fast det är den inte alltid, tyvärr.
Nu har jag suttit ett tag och försökt identifiera när attribut inte omges av dubbelfnuttar mha regexp, men det vill sig inte. När fnuttarna inte finns där öht får jag ingen träff.. hur kommer det sig?
Jag har gjort ett litet JUnit-test och test #1 går igenom som det skall men desvärre tycks det vara omöjligt för mig att se varför #2 inte går igenom.
public class HTMLAttributeTest extends TestCase {
Pattern pattern = null;
Matcher matcher = null;
protected void setUp() throws Exception {
}
protected void tearDown() throws Exception {
pattern = null;
matcher = null;
}
public void testSingleQuotes() throws Exception {
pattern = Pattern.compile("\\<.*?\\s+\\w+\\=\'(.*?)\'.*?\\>", Pattern.CASE_INSENSITIVE);
matcher = pattern.matcher("<td valign='top'>apa</td>");
assertTrue("Expected a match but no such luck.", matcher.matches() && matcher.group(1).equalsIgnoreCase("top"));
}
public void testMissingQuotes() throws Exception {
pattern = Pattern.compile("\\<.*?\\s+\\w+\\=(.*?).*?\\>", Pattern.CASE_INSENSITIVE);
matcher = pattern.matcher("<td width=610>banan</td>");
assertTrue("Expected a match but no such luck.", matcher.matches() && matcher.group(1).equals("610"));
}
}
Förtydligande: test #2 returnerar ju true för matcher.matches() men matcher.group(1) ger inte 610?
TomasJMedlem sedan feb. 200563 inlägg Om du vill slippa parsa med reguljära uttryck kan du prova att använda JTidy eller TagSoup
Angående reguljära uttryck som kan extrahera ett attributvärde, oavsett om det börjar med enkelfnuttar,
dubbelfnuttar eller inga fnuttar, så kan man speca en matchning på att attributvärdet ska börja efter noll
eller en förekomst av dubbelfnutt eller enkelfnutt (samt avslutas med fnutt eller space eller ">").
Ungefär så här alltså:
"<.*?=['\"]?(.*?)['\" >].*"
Ovanstående reguljära uttryck borde kunna hantera följande alternativ av html-element som har precis ett attribut:
<td width='610'>banan</td>
<td width=\"610\">banan</td>
<td width=610>banan</td>
<td width=610 >banan</td>
dAEk skrev:
...
assertTrue("Expected a match but no such luck.", matcher.matches() && matcher.group(1).equals("610"));
}
}
Förtydligande: test #2 returnerar ju true för matcher.matches() men matcher.group(1) ger inte 610?
Om du använder assertEquals så kan din utvecklingsmiljö (åtminstone om du använder Eclipse) visa vilket resultat du får istället för 610:
assertTrue("Expected a match but no such luck.", matcher.matches());
assertEquals("610", matcher.group(1));
/ Tomas
dAEkMedlem sedan feb. 20041 816 inlägg Sweet. Ska kika på det när jag kommer hem. Det verkar vettigt det du säger, det mesta faktiskt. Att jag inte tänkte på en HTML-parser själv... :OO
Tror även att jag ser var jag tänkte fel med min regexp.
Funkar superbra, tack, tack! (y)