954,517 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Fetch a node based on a value of another node.

I have XML data where information in nodes relate to other nodes. I am trying to figure out how to generate output based on these relationships.

XML sample
@F002@
...
@I005@@I007@

XSLT sample

Test

The above does not work, but hopefully gives an idea of what I am trying to do. Ultimately I would like to recurse through INDI nodes to related FAM nodes back to related INDI nodes.

Is this even possible with basic XSLT and XPATH functionality?

iskinner
Newbie Poster
6 posts since Feb 2011
Reputation Points: 10
Solved Threads: 0
 

xml for testing

<gedcom>
	<indi id="@I001">
		<famc>@F002@</famc>
	</indi>
	<fam id="@F002">
		<husb>@I005@</husb>
		<wife>@I007@</wife>
	</fam>
</gedcom>

xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output indent="yes" method="xml"/>
	<xsl:template match="/">
		<root>
			<xsl:apply-templates select="gedcom"/>
		</root>
	</xsl:template>
	<xsl:template match="gedcom">
		<xsl:apply-templates select="indi"/>
	</xsl:template>
	<xsl:template match="indi">
		<xsl:apply-templates select="famc"/>
	</xsl:template>
	<xsl:template match="famc">
		<famc>
			<where>
				<xsl:value-of select="."/>
			</where>
<!-- delete last sign @ and select the node 2 level back in same level as 
node fam indi
-->
			<xsl:variable name="data" select="substring(.,1,string-length(.)-1)"/>
			<xsl:apply-templates select="../../fam[@id=$data]"/>
		</famc>
	</xsl:template>
	<xsl:template match="fam">
		<datainfam>
				<xsl:apply-templates/>
		</datainfam>
	</xsl:template>
	<xsl:template match="husb|wife">
		<data>
			<xsl:value-of select="concat(local-name(.),' ',.)"/>
		</data>
	</xsl:template>
</xsl:stylesheet>

result

<?xml version='1.0' ?>
<root>
  <famc>
    <where>@F002@</where>
    <datainfam>
		
      <data>husb @I005@</data>
		
      <data>wife @I007@</data>
	
    </datainfam>
  </famc>
</root>
xml_looser
Junior Poster
179 posts since Apr 2009
Reputation Points: 16
Solved Threads: 21
 

Thank You XML Looser

But applying your code to my XML does not produce the expected output.

<root>
  <famc>
    <where>@F002@</where>
  </famc>
  <famc>
    <where>@F003@</where>
  </famc>
  <famc>
    <where>@F001@</where>
  </famc>
  ...
</root>

As you can see there is no datainfam nor their data nodes.

I see now that I mistyped the XML in my first example. All the ID values are escaped by two @ symbols.

<gedcom>
  <indi id="@I001@">
    <famc>@F002@</famc>
  </indi>
  ...
  <fam id="@F002@">
    <husb>@I005@</husb>
    <wife>@I007@</wife>
  </fam>
</gedcom>


So with that expectation, I simplified the famc match block.

<xsl:template match="famc">
  <famc>
    <where>
      <xsl:value-of select="."/>
    </where>

    <xsl:variable name="data" select="."/>
    <xsl:apply-templates select="../../fam[@id=$data]"/>
  </famc>
</xsl:template>

And this did not produce the desired output. I don't see how my correction would have broken things. I wonder if this could be a difference in parsers?

iskinner
Newbie Poster
6 posts since Feb 2011
Reputation Points: 10
Solved Threads: 0
 

Never mind!

I just corrected an incorrect case in one of the lines of code.

Now, I will play with this and see if I can get it to produce the desired HTML output!

Thanks again XML Looser. Your code has given me a very good start, I hope.

iskinner
Newbie Poster
6 posts since Feb 2011
Reputation Points: 10
Solved Threads: 0
 

a template descrip what will do when node is found by parser
all xml docment have an root element
so we can write the html code which is in the output display
with xsl:apply-templates select="gedcom" fetch the data and open table

<xsl:template match="/">
		<html>
			<style>
			table{border :black 2px solid}
			th,td{border :black 2px solid}
			</style>
			<table>
				<tr>
					<th>where</th>
					<th>item</th>
					<th>item</th>
				</tr>
				<xsl:apply-templates select="gedcom"/>
			</table>
		</html>
	</xsl:template>


use predicate as if in programming languarge

<xsl:variable name="data" select="substring(.,1,string-length(.)-1)"/>
<xsl:apply-templates select="../../fam[@id=$data]"/>


when data found put the value in a table

<xsl:template match="husb|wife">
		<td>
			<xsl:value-of select="concat(local-name(.),' ',.)"/>
		</td>
	</xsl:template>


xml tesdata

<gedcom>
	<indi id="@I001">
		<famc>@F002@</famc>
	</indi>
	<fam id="@F002">
		<husb>@I005@</husb>
		<wife>@I007@</wife>
	</fam>
	<indi id="@I001">
		<famc>@F003@</famc>
	</indi>
	<fam id="@F003">
		<husb>@I015@</husb>
		<wife>@I017@</wife>
	</fam>
</gedcom>

xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output indent="yes" method="html"/>
	<xsl:template match="/">
		<html>
			<style>
			table{border :black 2px solid}
			th,td{border :black 2px solid}
			</style>
			<table>
				<tr>
					<th>where</th>
					<th>item</th>
					<th>item</th>
				</tr>
				<xsl:apply-templates select="gedcom"/>
			</table>
		</html>
	</xsl:template>
	<xsl:template match="gedcom">
		<xsl:apply-templates select="indi"/>
	</xsl:template>
	<xsl:template match="indi">
		<xsl:apply-templates select="famc"/>
	</xsl:template>
	<xsl:template match="famc">
		<tr>
			<td>
				<xsl:value-of select="."/>
			</td>
			<xsl:variable name="data" select="substring(.,1,string-length(.)-1)"/>
			<xsl:apply-templates select="../../fam[@id=$data]"/>
		</tr>
	</xsl:template>
	<xsl:template match="fam">
		<xsl:apply-templates/>
	</xsl:template>
	<xsl:template match="husb|wife">
		<td>
			<xsl:value-of select="concat(local-name(.),' ',.)"/>
		</td>
	</xsl:template>
</xsl:stylesheet>

result

<html>
  <style>
			table{border :black 2px solid}
			th,td{border :black 2px solid}
			</style>
  <table>
    <tr>
      <th>where</th>
      <th>item</th>
      <th>item</th>
    </tr>
    <tr>
      <td>@F002@</td>
		<td>husb @I005@</td>
		<td>wife @I007@</td>
	</tr>
    <tr>
      <td>@F003@</td>
		<td>husb @I015@</td>
		<td>wife @I017@</td>
	</tr>
  </table>
</html>
xml_looser
Junior Poster
179 posts since Apr 2009
Reputation Points: 16
Solved Threads: 21
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: