PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : string aus textknoten mit knoten replacen


Coreyl
27.02.2006, 11:59
moin Cb...
folgendes xml gegeben:


<root>
<tag>
<knoten1> Textknoten ohne Inhalt der geändert wird.
</knoten1>
</tag>
<tag>
<knoten2> Textknoten mit Inhalt der geändert wird.
</knoten2>
</tag>
</root>


Ich suche das XML nach textknoten durch die ein bestimmtes Wort enthalten, im bsp.: "Inhalt"

Nun soll das Wort "Inhalt" mit einem Tag ersetzt werden, etwa:
<b>Inhalt</b> o.ä.

Das ganze findet statt im VS05, c#!

Mein Lösungsansatz:
string einlesen, aufteilen in 3 bereiche (Vor dem zu ersetzenden Wort, das Wort, nach dem ersetzenden Wort)
appende den ersten teil an die ParentNode, den mittelteil wie gewünscht, dannach den 3ten Teil.

Suche nach einer Performanteren (oder schöneren) Lösung, irgendwas mit innerxml oder sowas, hab aber weiterhin keinen anderen Konkreten ansatz (o. finden können)


eViL_oNe
27.02.2006, 20:33
die von dir beschriebene Lösung mit dem Erzeugen von Subnodes ist nicht nur die schönste (wenn auch sicherlich nicht die komfortabelste), sondern auch imo die einzige nach DOM mögliche.

Im Prinzip hast du ja vorher einen PCDATA Unterknoten mit dem Textinhalt.

1. Du erzeugst zwei weitere Unterknoten (einen b-Knoten und einen Textknoten)
2. der Inhalt des vorher schon bestehenden Knoten wird auf den ersten Substring abgekürzt
3. der zu ersetzende Inhalt wird in den ersten neuen Unterknoten als Textknoten geschrieben
4. in den zweiten neuen Unterknoten kommt der Rest des Textes

Coreyl
28.02.2006, 09:27
hm hab gestern weng rumprobiert...
problem bei der ganzen sache: nach jedem schritt wo ersetzt wird müssen wohl alle textknoten etc. neu eingelesen werden.

wer mich jetzt nochmal ransetzen und das grosse geschnipsel starten (hatte gestern schon was aber hatte fehler...
Jedoch grad etwas gefunden das mir wohl helfen könnt.

setz mich erstmal hin...

Coreyl
28.02.2006, 11:26
momentane lösung (falls es mal einer brauch)

IDictionaryEnumerator myHTEnum = myHT.GetEnumerator();
XmlNodeList nodeList = doc.SelectNodes("//text()");
while (myHTEnum.MoveNext())
{
foreach (XmlText textNode in nodeList)
{
if (textNode.Value.Contains(myHTEnum.Key as string))
{
string oldValue = myHTEnum.Key as string;
string newValue = myHTEnum.Key as string + "(" + myHTEnum.Value as string + ")";
XmlElement myDivElem = doc.CreateElement("div");
myDivElem.SetAttribute("class", "replace");
myDivElem.InnerText = newValue;
int getpos = textNode.Value.IndexOf(myHTEnum.Key as string);
textNode.ReplaceData(getpos, myHTEnum.Key.ToString().Length, myDivElem.OuterXml);
}
}
nodeList = doc.SelectNodes("//text()");
}

zu ersetzende wörter kommen aus der hashtable (key, value- paar als identifier für wörter + container für neuen inhalt)
enumerator geht jeden wert in der HT durch, und checkt jeden textknoten ob das wort vorhanden ist.
einzigstes problem:
< und > werden rausescaped, z.B. falsche darstellung im texteditor o.ä.
im ie z.B. oder per validation aber alles korrekt.

anderes problem:
ich kann die erstellten tags NICHT ansprechen.

XmlNodeList divlist = doc.GetElementsByTagName("div");
Console.Write(divlist.Count);

gibt "0" aus (int).
lösung?

Coreyl
02.03.2006, 13:33
der muell raubt mir nochn letzten nervenstrang

alles funktioniert nicht so wie es soll :D
was klar ist:
bestimmte elemente im textknoten sollen geändert werden und an deren stelle ein tag auftauchen.
ich poste euch hier meine (dummy) xml mit der ich arbeite:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<nodecontainer>
<lala attr="nooo">
</lala>
<jabba/>
<Olympia>das ist mein blindtext
</Olympia>
<grak attr="yeah">nochmehr blindtext
<ingrak>Olympia
</ingrak>und weitere...
</grak>
<mok>mok text ist gut!
<inmok>Weltmeisterschaft
</inmok>
</mok>
<malgug attr="nooo" blub="attributeownen">Das ist toll: Europameisterschaft
</malgug>
<more Olympia="Europameisterschaft">Tennis, Golf
<gym>Gymnastik
</gym>Turnen Weltmeisterschaft Weltmeisterschaft
<hatzu>Weitsprung
</hatzu>
Olympia, Weltmeisterschaft
<aga>Tennis
</aga>
</more>
<alles attr="nooo" blub="jabba!!!">Olympia, Weltmeisterschaft, Europameisterschaft, ich bin die Meisterschaft, Tennis, Golf, Gymnastik, Turnen, Weitsprung, Europameisterschaft!!
</alles>
</nodecontainer>
</root>

meine wörter die ich hier durch einen tag ersetzen will sind:
Welt-, Europameisterschaft sowie Olympia
meine hashtable:

public static Hashtable HTgen()
{
Hashtable HT = new Hashtable();
//Key = gesuchtes Wort, Value = Arraylist der sekundärwörter / worte
#region Olympia
ArrayList olympList = new ArrayList();
olympList.Add("Turin");
olympList.Add("Peking");
string olympValue = "";
foreach (string liItem in olympList)
{
olympValue += liItem + " ";
}
HT.Add("Olympia", olympValue);
#endregion
#region Weltmeisterschaft
ArrayList weltmList = new ArrayList();
weltmList.Add("Korea");
weltmList.Add("Deutschland");
string weltmValue = "";
foreach (string liItem in weltmList)
{
weltmValue += liItem + " ";
}
HT.Add("Weltmeisterschaft", weltmValue);
#endregion
#region Europameisterschaft
ArrayList europmList = new ArrayList();
europmList.Add("EM VALUE");
string europmValue = ("");
foreach (string liItem in europmList)
{
europmValue += liItem + " ";
}
HT.Add("Europameisterschaft", europmValue);
#endregion
return HT;
}

wobei der value aussenvor ist, wichtig erstmal nur das die gesuchten wörter an der RICHTIGEN position sind/bleiben mit umschliessendem <span> tag:

static void Replacing(Hashtable myHT, XmlDocument doc)
{
IDictionaryEnumerator myHTEnum = myHT.GetEnumerator();
XmlNodeList nodeList = doc.SelectNodes("//text()");
XmlText[] nodeArray = new XmlText[nodeList.Count];
int i = 0;
foreach (XmlText textNode in nodeList)
{
nodeArray[i++] = textNode;
}
foreach (XmlText textNode in nodeArray)
{
while (myHTEnum.MoveNext())
{
string myhtkey = myHTEnum.Key as string;
if (textNode.Value.Contains(myhtkey))
{
string textnodeValue = textNode.Value;
int getIndex = textnodeValue.IndexOf(myhtkey);
string prefixValue = textnodeValue.Substring(0, getIndex);
string begriff = textnodeValue.Substring(getIndex, myhtkey.Length);
//begriff = myHTEnum.Value as string;
string suffixValue = textnodeValue.Substring(getIndex + myhtkey.Length);
textNode.Value = prefixValue;
XmlElement mySpanElem = doc.CreateElement("span");
mySpanElem.SetAttribute("class", "replace");
XmlText begriffNode = doc.CreateTextNode(begriff);
mySpanElem.AppendChild(begriffNode);
textNode.ParentNode.AppendChild(mySpanElem);
XmlText suffixNode = doc.CreateTextNode(suffixValue);
textNode.ParentNode.AppendChild(suffixNode);
}
}
myHTEnum.Reset();
}
}


die main:

static void Main(string[] args)
{
XmlDocument doc = docload();
Hashtable myHT = Generation.HTgen();
Replacing(myHT, doc);
doc.Save("myoutput.xml");
}

docload läd die xml (return xmldokument), Generation ist meine klasse für die HT (unerheblich)


nur es funktioniert entweder nicht weil:
-string replace darf nicht sein! es müssen knoten hinzugefügt werden
-nicht alle wörter werden geändert (bei mehreren in einem textknoten)
-knoten werden an falsche "parents" o.ä. angehängt => der Ort des textes soll sich nicht ändern!

ich bekomms einfach nicht hin und hab schon fast keine lust mehr (ca. 1 woche nun)
dr. g und usenet = fehlanzeige
lösungsansätze?! *verzweifel :mauer::mauer:

e: das soll inetwa rauskommen (ausschnitt aus xml):

...
<grak attr="yeah">nochmehr blindtext
<ingrak><span class="replace">Olympia</span>
</ingrak>und weitere...
</grak>
<mok>mok text ist gut!
<inmok><span class="replace">Weltmeisterschaft</span>
</inmok></mok>
<malgug attr="nooo" blub="attributeownen">Das ist toll: <span class="replace">Europameisterschaft</span>
</malgug>
...