ugrás a tartalomhoz

javascript - xml nodeset

inf · 2011. Már. 15. (K), 04.21
Üdv.

Van egy elég komoly problémám msie xml node-jaival. Egyrészt objektumokhoz szeretném kötni őket, másrészt pedig ha Set-be teszem őket, akkor szeretném kizárni az egyezőségeket (szóval hogy ugyanaz a node többször szerepeljen). Az a gond, hogy nem lehet egyedi azonosítót rendelni a node-okhoz.

Ezt úgy próbáltam, hogy

Object.prototype.hashCode=(function ()
{
	var code=0;
	var property="HASHCODE";
	return function ()
	{
		if (!Object.prototype.hasOwnProperty.call(this,property))
		{
			this[property]=++code;
		}
		return this[property];
	}
})();

var dom=new ActiveXObject("MSXML2.DOMDocument.3.0");
dom.async=false;
dom.loadXML(
	'<cars>'+
		'<car><id>1</id><name>Volvo</name></car>'+
		'<car><id>2</id><name>VW</name></car>'+
		'<car><id>3</id><name>Mercedes</name></car>'+
		'<car><id>4</id><name>Bugatti</name></car>'+		
	'</cars>'
);

var hashCode=Object.prototype.hashCode.call(dom);
A gond ott van, hogy az xml node valamiért nem Object, ezért ilyen klasszikus dolgok, mint mondjuk egy tulajdonság beállítása nem működnek rajta. Van valakinek bármi ötlete, hogy hogyan lehetne azonosítani a dom node-okat?
(Egyelőre arra gondoltam, hogy az attribútumok közé teszem be a hashcode-ot, csak az a gond, hogy nem minden node-nak vannak attribútumai... :S)
 
1

setAttribute

Poetro · 2011. Már. 15. (K), 04.45
Esetleg érdemes megnézni az általános DOM programozást. Nem JavaScript-re gondolok a DOM egy nyelveken felüli dolog. Nem tudom, rendelkezik-e setAttribute tulajdonsággal, de ha nem, akkor lehet még kísérletezni az attributes objektummal.
2

Tudtommal csak

inf · 2011. Már. 15. (K), 17.11
Tudtommal csak ElementNode-nak vannak attribútumai, szóval DocumentNode vagy TextNode esetében ez a megoldás semmit sem ér. Hmm, még a constructor tulajdonság, amivel lehet, hogy megpróbálkozok, kíváncsi vagyok olyanja van e :-) Persze ez gányolás, dehát msie mindig gányolásra készteti az embert :S Valahova meg csak le kell rakni azt a hashCode-ot...

szerk:
A konstruktort lekérni le lehet, de beállítani ugyanúgy nem. Úgy néz ki, hogy esélytelen a dolog.

Még annyit lehet tenni, hogy a NodeSet-emet úgy írom meg, hogy minden új node hozzáadásánál végigmegyek rajta, és megnézem, hogy szerepel e már a node a gyűjteményben. Ez viszont eléggé lassít, szóval inkább hagyom az egészet.

Na jó, végülis jobb, mint a semmi:

(function ()
{
	var code=0;
	var property="HASHCODE";
	
	Object.prototype.hashCode=function ()
	{
		if (!this.hasOwnProperty(property))
		{
			this[property]=++code;
		}
		return this[property];
	};
	
	var nonObjects=
	{
		hashCode: function (nonObject)
		{
			for (var i in this)
			{
				if (this.hasOwnProperty(i) && this[i]===nonObject)
				{
					return i;
				}
			}
			this[++code]=nonObject;
			return code;
		}
	};

	Object.identify=function (o)
	{
		if (o.hashCode)
		{
			return o.hashCode();
		}
		else
		{
			return nonObjects.hashCode(o);
		}
	};
})();




var dom=new ActiveXObject("MSXML2.DOMDocument.3.0");
dom.async=false;
dom.loadXML(
	'<cars>'+
		'textNode'+
	'</cars>'
);

var cars=dom.childNodes[0];
var textNode=cars.childNodes[0];

alert(Object.identify(dom)+"="+Object.identify(dom)); //1=1
alert(Object.identify(cars)+"="+Object.identify(cars)); //2=2
alert(Object.identify(textNode)+"="+Object.identify(textNode)); //3=3

Csak hát ahogy nő az elemszám, úgy fog lassulni az egész. Egy nagyobb XML-nél szerintem nagyon hamar meghal msie. Azzal lehetne még gyorsítani a dolgon, hogy sima tömbben nézzük végig az elemeket, hashCode-ot nem használunk, és nodeType szerint csoportosítunk. Úgy talán elfogadható lenne az egész (úgy 100 elemes tömbig). Számomra most lett nyilvánvaló, hogy XML-el annyit fogok foglalkozni js-el, hogy XSLT-vel transzformálom, meg hogy objektumok alapján létrehozom, és elküldöm a szervernek.

Ha nem retardáltak írták volna msie-t, akkor jó lenne Model-nek MVC mintához. Talán még XHTML custom tagekkel lehetne valami hasonlót tenni, de őszintén szólva már elment a kedvem ettől az egésztől. Több értelme van építeni egy saját fát, aztán azon navigálni, mint XML-en, az xpath,xslt,xsd miatt jelentett volna valami előnyt.
3

htc-vel meg lehet oldani

inf · 2011. Ápr. 7. (Cs), 23.53
htc-vel meg lehet oldani HTML-re az ElementNode-okra szintúgy...
htc azért jobb egy fokkal, mert az attribútumokhoz való hozzáférés nagyon lassú
XML-nél még mindig nem találtam megoldást, csak az attribútumozás jöhet szóba

Hát szerintem elég gáz dolog, hogy ilyen gyermeteg hiba miatt nem lehet egy normális keretrendszert tákolni XML-hez. Ha az ember belegondol, úgy logikus, hogy az Object.prototype-ban levő dolgokat minden objektum örökölje, nem értem, hogy ettől miért kell vagy miért jó eltérni??? Mondjuk azt sem tudom, hogy a w3c ajánlást miért nem lehet követni. Ennyi év után sem tudom felfogni...
5

Hello!

Karvaly84 · 2011. Ápr. 8. (P), 08.33
Nem olyan rég próbálkoztam ilyenféle dolgokkal én is. Megjegyzem én csak ismerkedem evvel a JavaScript, DOM dologgal, de rájöttem pár dologra a kísérletek során:

A kísérleteimet XHTML 1.0 Strict DTD mellet hajtottam végre, és elég érdekes és bosszantó következtetéseket vontam le.

Röviden a lényeg:

A Node "appendChild" metódusát akartam felülírni úgy hogy csinálja meg a dolgát meg plusz amit hozzá írok.

Ezt teszteltem egy div-ben, ami a HTMLDivElement származéka.
Opera, Chrome: hibátlanul müködött,
Firefox: csak akkor ment ha a HTMLDivElement appendChild metódusát írtam felül,
Explorer: Itt nincs Node->(agyrém), Element van, átírtam, nem ment, átírtam a HTMLDivElement-et, de még úgy sem ment.

A másik már nem tudom melyiknél de volt olyan böngésző is ahol pl.: Element.prototype.valami = 'valamiszöveg' és utána ha ki kapsz a sorból mondjuk egy div-et és átírod a valami tulajdonságát arra h 'másikszöveg' akkor a többi elem valami tulajdonsága is megváltozik arra, hogy 'másikszöveg'.

Ezek alapján, simán lehet, hogy Explorer-ben az Object.prototype nincs hatással a DOM osztályokra.

Esetleg egy cikk jó lenne ebben a témában, mert agyrém, hogy egyes gyártók mennyire nem kompatibilisek a W3C DOM ajánlásával.
6

Az alap böngésző objektumok

Hidvégi Gábor · 2011. Ápr. 8. (P), 09.18
Az alap böngésző objektumok kiegészítése vagy felüldefiniálása nem biztos, hogy a legbölcsebb döntés. Képzeld el, hogy használsz az oldaldon egy másik, hasonlóan operáló függvénytárat, amelyik ugyancsak átírja azokat a függvényeket, amit te, aztán csodálkozol, hogy vagy a te kódod, vagy a másik nem fut le jól.
7

Világos, tisztában vagyok a

Karvaly84 · 2011. Ápr. 8. (P), 09.28
Világos, tisztában vagyok a kockázatokkal és mellékhatásokkal! Csak hadgyakorlat volt. :)
4

Egyébként mit akarsz kezdeni

Hidvégi Gábor · 2011. Ápr. 8. (P), 08.10
Egyébként mit akarsz kezdeni a nyers XML objektumokkal? Elég nehézkes a kezelésük, miért nem transzformálod át őket helyből valami JS tömbbé vagy HTML-lé, aztán nem kéne velük vacakolni.
8

Hát én most már semmit nem

inf · 2011. Ápr. 8. (P), 14.17
Hát én most már semmit nem akarok kezdeni velük. Az volt a tervem, hogy írok egy szép kódot, amivel lehet XML-ben gányolni, aztán ugyanazt ráhúzom XHTML-re is, de már letettem róla, mert msie miatt nem megvalósítható. Úgy gondoltam, hogy minden DOM Node fölé teszek egy másik objektumot, ami például eseményeket is le tud tárolni.
pl:

var xml=new XML(
	"<cars>"+
		"<car><name>Volvo</name><color>red</color></car>"+
		"<car><name>Mercedes</name><color>grey</color></car>"+
		"<car><name>Porsche</name><color>red</color></car>"+
	"</cars>"
);


var redCars=xml.xpath("car[color='red']");

xml.getRootNode().on("append",function (newCar)
{
	alert("new car: "+newCar.getElementsByTagName("name"));
});

xml.getRootNode().appendChild(
	{
		"@tagName": "car",
		name: "Ferrari",
		color: "red"
	},
	{
		"@tagName": "car",
		name: "Bugatti Veyron",
		color: "blue"
	}
);

//new car: Ferrari
//new car: Bugatti Veyron


redCars.each(function (car)
{
	alert("red car: "+car.getElementsByTagName("name"));
});

//red car: Volvo
//red car: Porsche
//red car: Ferrari
Szóval valami olyan fára gondoltam, amin lehet xpath-el ugrálni, és ami eseményeket is képes lekezelni. Innen kb egy lépés, hogy ehhez hozzácsapunk egy XMLView-t, ami automatikusan változik, ha események történnek, szóval ha módosítjuk a fát. Aztán az XML XSLT-vel szerializálható, és tetszőleges formában (ha az xml nem tetszik) átküldhető a szervernek. XML-ben nagyon sok potenciál lenne, ha engednék, hogy kihasználjuk. Így viszont csak az XSLT ami marad :S.

A másik, hogy az XML Node-ok fölé ugyanígy saját osztályú objektumokat lehetne tenni, úgy, hogy az xpath támogatottság megmaradna a fa bejárására.

var carTree=new CarsXML(
	"<cars>"+
		"<car><name>Volvo</name><color>red</color></car>"+
		"<car><name>Mercedes</name><color>grey</color></car>"+
		"<car><name>Porsche</name><color>red</color></car>"+
	"</cars>"
);
var carList=carTree.getCarList();
var redCars=carList.select({color: "red"});
alert(redCars);
// Volvo, Porsche
// (Car.toString -> name)

var greyCars=carTree.xpath("car[color='grey']");
alert(greyCars);
// Mercedes

carList.add(
	new Car(
	{
		name: "Ferrari",
		color: "red"
	})
);
alert(redCars);
// Volvo, Porsche, Ferrari
Ez az egész amúgy hasonlít arra, amit XFORMS-ban csinálnak. Szóval, hogy XML-ben van a model rész.

Nagyjából az volt a terv, hogy a model xml-t vagy annak egy részét visszaküldöm a szervernek, ahol xsd-vel ellenőrzöm, majd ha valid, akkor meghívom rá az aktuális action-t. Kirajzolásnál a model xml megjönne a szervertől, ráküldenék egy xsl-t, ami html-re transzformálná, és ennyi. A dolgot még XML adatbázissal lehetett volna megbonyolítani, de úgy látszik, hogy nem lesz belőle semmi, mert nagy munka lenne, és már ennél a résznél elakadt.

Lebutított változatban lehetne olyat, hogy az xsl-el létrehozom a view részt, plusz párhuzamosan json-ra konvertálom az xml-t, aztán a js objektumokkal dolgozok, majd a visszaküldésnél átkonvertálom őket xml-re.
9

Szuper ötlet, és szerintem

Hidvégi Gábor · 2011. Ápr. 8. (P), 15.16
Szuper ötlet, és szerintem egy jól megírt wrapperrel kivitelezhető is; az más kérdés, hogy IE alatt nem lenne gyors. A DOM műveletek mondjuk amúgy is lassúak, JS-ből pedig pláne.

Az XML-ben valóban nagyon nagy a potenciál, én már jóideje játszom XSLT transzformációkkal, és nagyon pozitív eredményeket értem el, csak idő hiányában még egyszerűen nem tudtam publikálni.
10

Jah, én is szeretem az XML-t

inf · 2011. Ápr. 8. (P), 15.22
Jah, én is szeretem az XML-t :-) Időm sajnos nekem sincs túl sok, most diplomázom, és inkább azzal foglalkozom. Lehet, hogy a programozást szüneteltetem pár évre, amíg a szakmámban előrébb jutok.
11

Úgy gondoltam, hogy minden

Karvaly84 · 2011. Ápr. 8. (P), 19.30
Úgy gondoltam, hogy minden DOM Node fölé teszek egy másik objektumot, ami például eseményeket is le tud tárolni.


Bocsi csak hogy tanuljak is valamit, leírnád nekem röviden mit értesz az alatt, hogy hogy fölé teszel egy objektumot, és hogy hogyan?
12

Ja bocs, úgy értem, hogy fölé

inf · 2011. Ápr. 8. (P), 20.49
Ja bocs, úgy értem, hogy fölé teszek minden Node-nak egy-egy Proxy objektumot, amin keresztül elérem őket. A Proxy-kat így tetszőleges kóddal lehet bővíteni, mondjuk meg lehet oldani, hogy a Proxy.appendChild(newProxy) meghívja a Node.appendChild(newNode)-ot, majd ezek után a Proxy.fireEvent("append",newProxy)-t. Így lehet mondjuk eseménykezelőket hozzáfűzni az egyes eseményekhez.

Ha a fenti példánál maradunk, akkor vannak a piros autók, mondjuk csinálsz egy olyan metódust, hogy CarListProxy.getRedCars(), ami a piros autókat adja vissza, és neked nem kell minden alkalommal megadni, hogy mi alapján választod ki az autókat. Mondjuk a RedCars az Selection típusú dolgot ad vissza, és a CarList.onAppend-jét figyeli. Ha az onAppend-nél vörös kocsit adnak hozzá, akkor felveszi az új kocsit a benne lévő elemek közé. (Persze ezt úgy is meg lehet oldani, hogy minden egyes használatkor végigmegy a teljes kocsi listán, és kiválasztja a vöröseket, kinek hogy tetszik.)

Ha van egy ilyen fád, akkor csinálhatsz hozzá CarListView-t, ami először végigmegy az összes kocsin, kirajzolja őket táblázatba, aztán utána figyeli az CarList.onAppend-et, és ha új kocsi kerül a listába, akkor frissíti a táblázatot. Így elég csak a CarList-el, szóval az adatokkal foglalkozni, a CarListView pedig automatikusan követi a változásokat. Gányoltam anno egy ilyen rendszerrel csak XML nélkül. Ott drag-droppal módosítottam egy fát, és egy oldal layout-ját rajzoltattam ki az alapján.

Ha HTML-t vesszük, akkor pedig a Proxy-kat ki lehet egészíteni setStyle meg hasonló metódusokkal. Az egésznek a kulcsa ott van, hogy a Node alapján meg kell tudni találni a hozzá tartozó Proxy-t.

Ha mondjuk csinálsz egy olyat, hogy Node.firstChild, akkor az az első gyereket adja vissza. Maradjunk a kocsis példánál:

<cars>
	<car><name>Volvo</name><color>red</color></car>
	<car><name>Mercedes</name><color>grey</color></car>
	<car><name>Porsche</name><color>red</color></car>
</cars>
carNode.firstChild => nameNode

Na most a nameNode az ugye itt XML Node, a hozzá tartozó Proxy-t meg le kell kérni valami alapján. Az Object.prototype.hashCode azért lenne jó ilyen célra, mert minden egyes objektumnak egy egyedi azonosítószámot ad, az azonosítószámok alapján pedig már lehet csinálni egy ProxyMap-et:
carProxy.first() => carNode.fistChild => nameNode
ProxyMap[nameNode.hashCode()] => nameProxy

Ez a ProxyMap visszaadja az adott Node-hoz tartozó Proxy-t. Így garantálható, hogy egy Node-hoz csak egy Proxy tartozik, és az végzi rajta az összes kényes műveletet. Ha több Proxy lenne egy Node-hoz, akkor nem tudnának egymás eseménykezelőiről, és teljes lenne a káosz...
Szóval az egésznek a kulcsa az, hogy be lehessen azonosítani 1-1 Node-ot az XML fán. Ha ez nem megy, akkor nem lehet új réteget építeni az XML fölé. Ha nem lehet egyedi azonosítót adni, akkor viszont a Proxy-t kell eltárolni valamilyen Node tulajdonságban, mondjuk
Node.proxy => Proxy

de ezt sem lehet megoldani, mert a Node-okhoz nem lehet tulajdonságokat adni. Ezért bukó az egész.
HTML-ben msie-nél htc-vel megoldható ElementNode-okra, de XML-el nem. (A többi böngészőben örökli az Object.prototype-ot a Node, szóval azokkal nincs gond.)
13

Értem

Karvaly84 · 2011. Ápr. 8. (P), 22.05
Bár ilyen tervezési mintákban nem vagyok jártas, mert magyar anyag igen kevés a témában de mintha azt érteném hogy ez egy Figyelő minta vagy minek nevezik, és egy absztrakt réteget képez "TE" és a "DOM" között. Na majd még olvasgatom amit irtál... Köszi hogy elmagyaráztad! BéKE
14

Helyettes (Proxy) Szerkezeti

inf · 2011. Ápr. 9. (Szo), 00.07
Helyettes (Proxy)
Szerkezeti objektumminta
Adott objektumot képviselőn vagy helyőrzőn keresztül irányítani, hogy szorosabban felügyelhessük a működését.

Megfigyelő (Observer)
Viselkedési objektumminta
Objektumok között egy-sok függőségi kapcsolatot létrehozni, így amikor az egyik objektum állapota megváltozik, minden tőle függő objektum értesül erről és automatikusan frissül.
15

Ilyen és ehez hasonlók?

Karvaly84 · 2011. Ápr. 9. (Szo), 00.24
Ha nem tartalak fel segítenél, hogy vannak olyan doksik cikk-ek amik ezekkel a kérdésekkel foglalkoznak?

Itt a weblabor-on vagy máshol.

Közbe már rá is keresek ezekre :)


/**
 * Kiegészítés
 * 
 * Esetleg, könyv is lehet amit meg lehet venni magyarul!
 * Ennek örülnék a legjobban :)
 */

 naExit('BéKE') // :)

16

Erich Gamma,Richard

inf · 2011. Ápr. 9. (Szo), 03.49
Erich Gamma,Richard Helm,Ralph Johnson,John M. Vlissides:
Design Patterns: Elements of Reusable Object-Oriented Software

Martin Fowler:
Refactoring: Improving the Design of Existing Code

Joshua Kerievsky:
Refactoring to Patterns

Robert C. Martin
Clean Code: A Handbook of Agile Software Craftsmanship

Többségét megtalálod magyarul is, de nincs sok értelme, mert a programozás nyelve az angol.
(Ettől függetlenül a Design Patterns nekem is Programtervezési Minták címmel van meg :-) )
17

Megnéztem a könyvet ma, de az

Karvaly84 · 2011. Ápr. 9. (Szo), 20.49
Megnéztem a könyvet ma, de az nem nekem való, mert én más nyelven programozok és inkább web-et, de helyette találtam egy könyvet: Webalkalmazások fejlesztése Ajax segítségével&nbsp;ebben van pár általános tervezési minta is, megvettem remélem beválik...
18

A mintáknál pont az a lényeg,

inf · 2011. Ápr. 9. (Szo), 22.23
A mintáknál pont az a lényeg, hogy nyelvfüggetlenek, én sem szoktam C-ben meg java-ban fejleszteni, de a legtöbb könyv, amit olvastam ezekhez kapcsolódik, mert ezekhez csinálnak színvonalas könyveket. Komoly alkalmazást nem fejleszt senki php alatt, szóval a php-s könyvekből nem hiszem, hogy meg lehet tanulni ilyesmiket.