2

I am currently developing a parser that reads xml and returns specific values into documents. I have a strange bit of XML that I am not sure how to deal with. Here is an example:

<record>
<field name="Agreement_Role:addonSection.effectiveStartTime">15/08/2014</field>
<field name="Agreement_Role:addonSection.effectiveEndTime">31/12/9999</field>
<field name="Agreement_Role:addonSection.addonProduct">Gen</field>
<field name="Agreement_Role:addonSection.addonType">ProtectPlus</field>
<field name="Agreement_Role:addonSection.premium">21.70</field>
<field name="Agreement_Role:addonSection.displayOrder">2</field>
<field name="Agreement_Role:addonSection.replaceAddonType">ProtectPlus</field>
<field name="Agreement_Role:addonSection.addonCode">ProtectPlus</field>
<field name="Agreement_Role:addonSection.status">Live</field>
<field name="Agreement_Role:addonSection.cancellationRefund">00</field>
<field name="Agreement_Role:addonSection.effectiveStartTime">15/08/2014</field>
<field name="Agreement_Role:addonSection.effectiveEndTime">31/12/9999</field>
<field name="Agreement_Role:addonSection.addonProduct">Gen</field>
<field name="Agreement_Role:addonSection.addonType">Bd 1</field>
<field name="Agreement_Role:addonSection.premium">35.85</field>
<field name="Agreement_Role:addonSection.displayOrder">4</field>
<field name="Agreement_Role:addonSection.replaceAddonType">Breakdown</field>
<field name="Agreement_Role:addonSection.addonCode">Bd 1</field>
<field name="Agreement_Role:addonSection.status">Live</field>
<field name="Agreement_Role:addonSection.cancellationRefund">00</field>
<field name="acceptanceType">tacitCard</field>
<field name="Type">default</field>
<field name="effectiveDate">17/08/2014 00:00:00 BST</field>
<field name="expiryDate">16/08/2015 23:59:59 BST</field>
<field name="creationDate">15/08/2014 13:27:52 BST</field>
<field name="acceptanceDate">15/08/2014 13:43:27 BST</field>
#other elements follow this format
</record>

Contained in this sample are two add-ons. I would like to use the addonType field to specify if the add-on is present, and if so, display the related premium.

The add-ons are not separated into parent elements. The sample i have provided is everything I get. So how would I choose between the two premium elements of identical name and path?

If it helps, the elements would always be in the same order, but I would like to avoid using that incase it is changed in the future.

Thanks

a.hrdie
  • 716
  • 2
  • 14
  • 35
  • Give us an example of output. – Alex Aug 20 '14 at 10:38
  • my output is a word document, formatted into a letter. I use Xpath to merge the fields into the templates. Ill add the full root element onto the sample – a.hrdie Aug 20 '14 at 10:52

1 Answers1

2

If it helps, the elements would always be in the same order, but I would like to avoid using that incase it is changed in the future.

From your sample the ordering appears to be the only thing grouping related elements - the sequence of elements from one effectiveStartTime to the first following cancellationRefund constitutes one group, the next group starts with the next effectiveStartTime, etc.

I suppose an alternative interpretation if you know the set of field names is fixed, would be to iterate over all instances of one particular field name, then pull out the related fields by position, i.e.

<xsl:for-each select="field[@name='Agreement_Role:addonSection.effectiveStartTime']">
  <xsl:variable name="pos" select="position()" />
  <addon>
    <effectiveStart><xsl:value-of select="."/></effectiveStart>
    <effectiveEnd>
      <xsl:value-of select="
        ../field[@name='Agreement_Role:addonSection.effectiveEndTime'][$pos]" />
    </effectiveEnd>
    <!-- and so on for the other field names -->
  </addon>
</xsl:for-each>

so for the nth effectiveStartTime you pull out the nth effectiveEndTime, etc. This would allow for the fields to appear in any interleaving, as long as the ordering between fields of the same name is consistent, e.g.

<field name="Agreement_Role:addonSection.effectiveStartTime">15/08/2014</field>
<field name="Agreement_Role:addonSection.effectiveStartTime">15/08/2014</field>
<field name="Agreement_Role:addonSection.effectiveEndTime">31/12/9999</field>
<field name="Agreement_Role:addonSection.effectiveEndTime">31/12/9999</field>
<field name="Agreement_Role:addonSection.addonProduct">Gen</field>
<field name="Agreement_Role:addonSection.addonProduct">Gen</field>
<field name="Agreement_Role:addonSection.addonType">ProtectPlus</field>
<field name="Agreement_Role:addonSection.addonType">Bd 1</field>
<field name="Agreement_Role:addonSection.premium">21.70</field>
<field name="Agreement_Role:addonSection.premium">35.85</field>
<field name="Agreement_Role:addonSection.displayOrder">2</field>
<field name="Agreement_Role:addonSection.displayOrder">4</field>
<field name="Agreement_Role:addonSection.replaceAddonType">ProtectPlus</field>
<field name="Agreement_Role:addonSection.replaceAddonType">Breakdown</field>
<field name="Agreement_Role:addonSection.addonCode">ProtectPlus</field>
<field name="Agreement_Role:addonSection.addonCode">Bd 1</field>
<field name="Agreement_Role:addonSection.status">Live</field>
<field name="Agreement_Role:addonSection.status">Live</field>
<field name="Agreement_Role:addonSection.cancellationRefund">00</field>
<field name="Agreement_Role:addonSection.cancellationRefund">00</field>

would give the same result.

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
  • Thank you, excellent way of using indices. I have implemented this into a transform and it is working. I will leave this for an hour or two to see if there is another way, then accept. Thank you very much – a.hrdie Aug 20 '14 at 13:07