I have this XML, that is a series of ContactInfo nodes, some contain the PostAddr, and some contain the PhoneNum. I have to match the ContactInfo node that contains the address with the one that contains the PhoneNum like this - the AddrSource tag value (in the ContactInfo nodes that contain address) should match the PhoneNum Source attribute value(from the ContactInfo nodes that contain phones).
This is a sample of the XML:
<ContactInfo Source="MB" EffDt="2022-10-11">
<PostAddr>
<StreetNum>xxx</StreetNum>
<StreetName>ATLANTA</StreetName>
<StreetType>HWY</StreetType>
<Apt>099</Apt>
<City>MONTGOMERY</City>
<StateProv>AL</StateProv>
<PostalCode>1000</PostalCode>
<County>MONTGOMERY</County>
<AddrType>S</AddrType>
<ReportedDt>2019-08-09</ReportedDt>
<AddrSource>3</AddrSource>
<AddrCreatedDt>2019-07-22</AddrCreatedDt>
</PostAddr>
</ContactInfo>
<ContactInfo Source="MB" EffDt="2022-10-11">
<PostAddr>
<StreetNum>09521</StreetNum>
<StreetName>STANTON</StreetName>
<StreetType>WAY</StreetType>
<Apt>APT 19080</Apt>
<City>PRATTVILLE</City>
<StateProv>AL</StateProv>
<PostalCode>111-111</PostalCode>
<County>AUTAUGA</County>
<AddrType>H</AddrType>
<ReportedDt>2019-04-09</ReportedDt>
<AddrSource>4</AddrSource>
<AddrCreatedDt>2019-04-03</AddrCreatedDt>
</PostAddr>
</ContactInfo>
<ContactInfo Source="MB" EffDt="2022-10-11">
<PhoneNum Source="3" EffDt="2022-10-11">
<PhoneType>OTHER </PhoneType>
<Phone>123224434</Phone>
</PhoneNum>
</ContactInfo>
<ContactInfo Source="MB" EffDt="2022-10-11">
<PhoneNum Source="4" EffDt="2022-10-11">
<PhoneType>OTHER /WIRELESS</PhoneType>
<Phone>30000</Phone>
</PhoneNum>
</ContactInfo>
Ultimately I need to be able to make a table in this format:
<table>
<tr>
<td>Address</td>
<td>Phone</td>
</tr>
</table>
What should be my approach here? I have been mainly working with for-each loops and choose but I can't seem to find a way to make them work here. I looked a bit into grouping but I wasn't able to apply that either, so I'm a bit stuck with this. Any help would be greatly appreciated.
CodePudding user response:
XSLT has a built-in key mechanism for resolving cross-references. Here's a minimal example:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="phone" match="PhoneNum" use="@Source" />
<xsl:template match="/*">
<table border="1">
<xsl:for-each select="ContactInfo/PostAddr">
<tr>
<td>
<xsl:value-of select="City"/>
</td>
<td>
<xsl:value-of select="key('phone', AddrSource)/Phone"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Applied to your input example - after adding a root element! - this will return:
Result
<?xml version="1.0" encoding="UTF-8"?>
<table border="1">
<tr>
<td>MONTGOMERY</td>
<td>123224434</td>
</tr>
<tr>
<td>PRATTVILLE</td>
<td>30000</td>
</tr>
</table>