Subject: Re: localization techniques and code review From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Mon, 20 Nov 2000 16:29:55 +0000 |
Haroon, >> The nested xsl:for-each is necessary. The key() function that you use >> is scoped by the current node: it only looks for nodes within the >> current document. In the outer xsl:for-each, the current document is >> your source XML. You need to change it to the localization.xml >> document to use the key to retrieve information quickly from it. > > I am confused about your statement about moving localization.xml to the > outer xsl:for-each. How would that be more advantageous? Would it change my > xsl:key? Sorry, I obviously didn't explain what I meant very well. You have two xsl:for-eaches: <!-- outer xsl:for-each --> <xsl:for-each select="field"> <xsl:variable name="field" select="." /> <xsl:value-of select="$field" /> <h1> <!-- inner xsl:for-each --> <xsl:for-each select="$trans"> <xsl:value-of select="key('translate',concat($field,'-',$selectLang))" /> </xsl:for-each> </h1> </xsl:for-each> and you asked: > 1. Am I on the right track? What about the use of nested > <xsl:for-each select="document('localization.xml')"> I wasn't advocating moving localization.xml to the outer xsl:for-each, but trying to explain why you need to have the nested xsl:for-eaches that you have. xsl:for-eaches change the current node. The current node is important because it is the base to which XPaths and some functions are relative. In this case, the key() function uses the current node to work out what document to search for the nodes that you are indexing into. If you didn't have the inner xsl:for-each, the key() function would use the current node set in the outer xsl:for-each (i.e. the 'field' element in your source XML) to work out what document to look in. Since the 'field' element is in the source XML, the key() function would look in the source XML document for the nodes. You defined your xsl:key as: <xsl:key name="translate" match="translation" use="concat(ancestor::word/@name,'-',@lang)" /> So, if there wasn't that inner xsl:for-each the key() function would attempt to look for 'translation' elements in the source XML for that particular word and language. Since there aren't any 'translation' elements in the source XML, it would come up with nothing. So, the point of the inner xsl:for-each is to change the current node to be a node in the localization.xml document. With that as the current node, the key() function correctly searches within the localization.xml document. > On another note, is there a way for me to modify the following statement to > only return nodes which match lang=$selectLang attribute? (the idea is to > filter non-chosen languages - could I use something like > [@lang='$selectLang']??) > <xsl:variable name="trans" select="document('localization.xml')" /> > How can the above statement be modified to achieve the above objective and > is that even something to consider? You could set your variable to just hold translations in a particular language within the XSLT, but I think it would be more trouble than it's worth. To set your variable to hold just these translations, you could use: <xsl:variable name="trans" select="document('localization.xml')/localization/word/translation[@lang = $selectLang]" /> You could then do the equivalent of the above xsl:for-eaches with: <xsl:for-each select="field"> <xsl:variable name="field" select="." /> <xsl:value-of select="$field" /> <h1> <xsl:value-of select="$trans[ancestor::word/@name = $field]" /> </h1> </xsl:for-each> Generally this is likely to be slower than using keys, especially if you have lots of fields to translate. If you're worried about the size of localization.xml and consequently the size of its DOM and the key's hashtable when the XSLT runs, then you are probably better off thinking in terms of a pre-process that filters the localization.xml file to only the language that you are actually interested in before running the main stylesheet on it. You could do this pre-processing with XSLT by creating a stylesheet that copies the relevant parts of localization.xml. The main stylesheet would then access the filtered information: you should change the way the key is declared and used to reflect this. > I am sorry. I think my choice of wording made you look deeper than I > intended. (My knowledge is not deep enough to think of document caching at > the server level :-)). I had meant to ask if I could re-print the results, > another time without having to re-document() the localization.xml file, > (perhaps in another style)? By clarifying the use of the $trans in: > <xsl:variable name="trans" select="document('localization.xml')" /> > I know now that it is re-usable and has all the nodes inside it. Just a clarification: it doesn't really have all the nodes inside it, it just holds a reference to one node, the document's root node. The thing is that anything else in the document can be accessed from that root node. There's a difference between: <xsl:variable name="trans" select="document('localization.xml')" /> which holds the root node of the document and: <xsl:variable name="trans" select="document('localization.xml')/*/word" /> which holds all the 'word' elements in the document. As an aside: probably as a hang over from using Saxon 5.4.something where multiple document() calls accessed the relevant document multiple times (a bug that's now fixed), I now always declare the extra documents that I use as global variables, and access them through that variable wherever I use them in the rest of the stylesheet. There's nothing wrong with accessing the document with several document() calls, and processors will generally reuse the DOM that they already have anyway, but having only one document() call gives you greater maintainability 'cos you only have to edit the name once if you move or rename the document, for example. I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: localization techniques and cod, Haroon Rafique | Thread | Referencing an attribute contains a, Dan Matthews |
Copying a portion of a subtree in i, Mike Mahoney | Date | Re: Node set comnparison, Jeni Tennison |
Month |