No faktycznie, przednia zabawa. Sęk w tym, że skoro na wejściu masz gotowy plik HTML, to nie wiem, czy nie byłoby lepiej skorzystać z bibliotek, które umożliwiają parsowanie HTML (dla .NET jest to np. http://forum.dobreprogramy.pl/wyrazenia-regularne-wyciaganie-danych-znacznikow-t476551.html). Teraz, gdy ten plik jest już taki “rozjechany”, to dużo rzeczy trzeba pisać samemu i nie można skorzystać z gotowca. W każdym bądź razie wrzucam zaktualizowany parser:
http://www.speedyshare.com/file/38wVy/Parser.exe (BTW Ty programujesz w .NET? Bo nie wiem, czy jest sens, żebym pokazywał kod)
Przy okazji dodam, że parser nie zadziała poprawnie, jeśli w jednej linijce będzie kilka tagów, np. kilka akapitów (
). Poszczególne tagi h i p muszą być oddzielone znakiem nowej linii (innymi słowy musi to wyglądać tak, jak w zamieszczonych przez Ciebie przykładach). Po tym co napisałeś zgaduję, że wcale tak nie musi być, czyli, że jeden akapit może zajmować np. kilka linijek lub np. znaczniki zamykający i otwierający mogą być zaraz obok siebie
. Możesz mi powiedzieć, czy tak faktycznie jest? Jeśli tak, to ten parser, Ci się nie przyda. Ja poprawek dalszych w takiej sytuacji wprowadzać nie będę, bo lepiej byłoby po prostu inaczej zabrać się do tego problemu (tak jak napisałem w pierwszym akapicie).
Klasa Tag
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Parser
{
public class Tag
{
public Tag()
{
Title = string.Empty;
Paragraphs = new List();
Tags = new Tags();
}
public string Title { get; private set; }
public List Paragraphs { get; private set; }
public Tags Tags { get; private set; }
public void Load(int startIndex, int endIndex, string[] lines)
{
Title = TagUtil.GetHTagContents(lines[startIndex]);
for (int i = startIndex + 1; i <= endIndex; i++)
{
int? tagLevel = TagUtil.GetTagLevel(lines[i]);
if (tagLevel.HasValue)
break;
string paragraph = TagUtil.GetPTagContents(lines[i]);
if (!string.IsNullOrEmpty(paragraph))
Paragraphs.Add(paragraph);
}
startIndex += 2;
if (startIndex <= endIndex)
Tags.Load(startIndex, endIndex, lines);
}
public XElement Save()
{
XElement result = null;
result = new XElement("section",
new XElement("title", new XElement("p", Title)));
if (Paragraphs.Count > 0)
result.Add(
from paragraph in Paragraphs
select new XElement("p", paragraph)
);
if (Tags.Count > 0)
result.Add(
from element in Tags.Save()
select element
);
return result;
}
}
}
Klasa Tags
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Parser
{
public class Tags : List
{
public Tags()
: base()
{ }
public void Load(string filePath, Encoding fileEncoding)
{
StreamReader reader = null;
List lines = new List();
try
{
reader = new StreamReader(filePath, fileEncoding);
string line = string.Empty;
while ((line = reader.ReadLine()) != null)
{
line = line.Trim();
if (!string.IsNullOrEmpty(line))
lines.Add(line);
}
}
catch { throw; }
finally
{
if (reader != null)
reader.Close();
}
Load(0, lines.Count - 1, lines.ToArray());
}
public void Load(int startIndex, int endIndex, string[] lines)
{
int? lowestTagLevel = TagUtil.GetTagLevel(lines[startIndex]);
if (!lowestTagLevel.HasValue)
return;
int? tagStartIndex = null;
for (int i = startIndex; i <= endIndex; i++)
{
int? tagLevel = TagUtil.GetTagLevel(lines[i]);
bool addTag = false;
if (tagLevel.HasValue && tagLevel == lowestTagLevel)
if (tagStartIndex == null)
tagStartIndex = i;
else
addTag = true;
if (addTag || (tagStartIndex.HasValue && (i + 1 > endIndex)))
{
int tagEndIndex = endIndex;
if (addTag)
tagEndIndex = i - 1;
Tag tag = new Tag();
tag.Load(tagStartIndex.Value, tagEndIndex, lines);
Add(tag);
tagStartIndex = null;
if (addTag)
tagStartIndex = i;
}
}
}
public void Save(string filePath)
{
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("root",
from element in Save()
select element
));
doc.Save(filePath);
}
public XElement[] Save()
{
var elements = from tag in this
select tag.Save();
return elements.ToArray();
}
}
}
Klasa TagUtil
using System.Text.RegularExpressions;
namespace Parser
{
public static class TagUtil
{
private static Regex pTagContentsRegex;
private static Regex hTagContentsRegex;
private static Regex tagLevelRegex;
static TagUtil()
{
string tagContentsFormat = "<.*?{0}.*?>(?.*?)<.*?/.*?{0}.*?>";
string pTagContents = string.Format(tagContentsFormat, "p");
string hTagContents = string.Format(tagContentsFormat, "h");
pTagContentsRegex = new Regex(pTagContents, RegexOptions.IgnoreCase | RegexOptions.Singleline);
hTagContentsRegex = new Regex(hTagContents, RegexOptions.IgnoreCase | RegexOptions.Singleline);
tagLevelRegex = new Regex(@"[\d]+)>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
}
public static string GetPTagContents(string line)
{
return pTagContentsRegex.Match(line).Groups["tagContents"].Value;
}
public static string GetHTagContents(string line)
{
return hTagContentsRegex.Match(line).Groups["tagContents"].Value;
}
public static int? GetTagLevel(string line)
{
string tagLevel = tagLevelRegex.Match(line).Groups["tagLevel"].Value;
if (string.IsNullOrEmpty(tagLevel))
return null;
return int.Parse(tagLevel);
}
}
}
Klasa Program
bez zmian