Subject: Re: [xsl] Merging XML data from different files From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Mon, 22 Jan 2001 22:30:13 +0000 |
Hi Matt, > I have multiple XML files, and I am able to combine the primary and > the secondary files according to an 'ID' in the first. There are > extra 'IDs' in the secondary files that I wish to join as well - How > do I go about this?? The elements in the secondary document(s) that do not have an equivalent element in the primary document are those for which it's not the case that their 'id' attribute (or whatever you've called your attribute) is the 'id' attribute of an element in the primary document. So, let's say that you've set the primary and secondary document root nodes as $doc1 and $doc2 with: <xsl:variable name="doc1" select="/" /> <xsl:variable name="doc2" select="document('secondary.xml')" /> You can get all the 'id' attributes in $doc1 with: $doc1//@id It may be worth setting up a variable to hold that list: <xsl:variable name="doc1IDs" select="$doc1//@id" /> You can get any elements in the secondary document with: $doc2//* You can get those whose 'id' attribute equals the 'id' attribute of an element in $doc1 with: $doc2//*[@id = $doc1IDs] So you can get those whose 'id' attribute *does not* equal the 'id' attribute of any element in $doc1 with: $doc2//*[not(@id = $doc1IDs)] So to add them to your result tree, you can just copy those nodes: <xsl:copy-of select="$doc2//*[not(@id = $doc1IDs)]" /> If you have really big documents with lots of IDs, then it might be worth using keys rather than a path like the above (or using id() if you have a DTD and the relevant attribute is defined as an ID attribute); if you use keys, then it makes things a little harder because of the way the scoping of keys works: they only retrieve nodes indexed by the key within the document holding the context node. The key would index all elements according to their 'id' attribute: <xsl:key name="elements" match="*" use="@id" /> So to get a list of them, you have to iterate over the elements in the secondary document (using xsl:for-each here for simplicity, but you could use xsl:apply-templates instead if you wanted): <xsl:for-each select="$doc2//*"> ... </xsl:for-each> You then need to record the element in the secondary document: <xsl:for-each select="$doc2//*"> <xsl:variable name="el2" select="." /> ... </xsl:for-each> before changing the current node to the primary document: <xsl:for-each select="$doc2//*"> <xsl:variable name="el2" select="." /> <xsl:for-each select="$doc1"> ... </xsl:for-each> </xsl:for-each> so that you can retrieve nodes using the key you've set up, test whether there is one, and if not then copy (or whatever) the element in the secondary document: <xsl:for-each select="$doc2//*"> <xsl:variable name="el2" select="." /> <xsl:for-each select="$doc1"> <xsl:if test="not(key('elements', $el2/@id))"> <xsl:copy-of select="$el2" /> </xsl:if> </xsl:for-each> </xsl:for-each> 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 -> |
---|---|---|
[xsl] Merging XML data from differe, mjyoungblut | Thread | [xsl] XSL-List guidelines -CHANGED!, Mulberry Technologie |
RE: [xsl] Attribute default values , Andrew Kimball | Date | [xsl] Changing <b> to "[", Edierley Messias |
Month |