Earl Gray
Earl Gray

Reputation: 13

XPath Identify all XML Elements by attribute value not known until runtime

I have an XML input file that looks like this:

<property>
<properties>
    <entry id="55882d2cacb45">
        <location_number>1</location_number>
        <building_number>1</building_number>
        <coverage source_id="55882d2cacb45">
            <name>building</name>
            <premium>2880</premium>
        </coverage>
        <coverage source_id="55882d2cacb45">
            <name>contents</name>
            <premium>1290</premium>
        </coverage>
        <coverage source_id="55882d2cacb45">
            <name>business</name>
            <premium>7780</premium>
        </coverage>
        <coverage source_id="55882d2cacb45">
            <name>inflationGuard</name>
            <premium>29</premium>
        </coverage>
        <coverage source_id="55882d2cacb45">
            <name>terrorism</name>
            <premium>353</premium>
        </coverage>
        <building>
            <entry id="55882d2cacb45">
                <building>1,000,000</building>
                <coverage_form>Class</coverage_form>
                <coverage source_id="55882d2cacb45">
                    <name>building</name>
                    <premium>2880</premium>
                </coverage>
                <group2_type>Symbol</group2_type>
            </entry>
        </building>
    </entry>
</properties>
<properties>
    <entry id="55882d2cacc68">
        <location_number>1</location_number>
        <building_number>2</building_number>
        <coverage source_id="55882d2cacc68">
            <name>building</name>
            <premium>749</premium>
        </coverage>
        <coverage source_id="55882d2cacc68">
            <name>contents</name>
            <premium>170</premium>
        </coverage>
        <coverage source_id="55882d2cacc68">
            <name>business</name>
            <premium>1095</premium>
        </coverage>
        <coverage source_id="55882d2cacc68">
            <name>inflationGuard</name>
            <premium>7</premium>
        </coverage>
        <coverage source_id="55882d2cacc68">
            <name>terrorism</name>
            <premium>63</premium>
        </coverage>
        <coverage source_id="55882d2cacc68">
            <name>theft</name>
            <premium>266</premium>
        </coverage>
        <building>
            <entry id="55882d2cacc68">
                <building>100,000</building>
                <coverage_form>Class</coverage_form>
                <coverage source_id="55882d2cacc68">
                    <name>building</name>
                    <premium>749</premium>
                </coverage>
                <group2_type>Symbol</group2_type>
            </entry>
        </building>
        <improvements>
            <entry id="55882d2cacc68">
                <improvements>5,000</improvements>
                <coverage_form>Class</coverage_form>
                <coverage source_id="55882d2cacc68">
                    <name>business</name>
                    <premium>1095</premium>
                </coverage>
                <group2_type>Symbol</group2_type>
            </entry>
        </improvements>
    </entry>
</properties>
<eb>
    <eb_total_insured_value>4155000</eb_total_insured_value>
    <coverage source_id="55882d2cacb45">
        <name>eb</name>
        <premium>2880</premium>
    </coverage>
</eb>
<value_pack>
    <coverage source_id="55882d2cacb45">
        <name>capacity_value_pack</name>
        <premium>600</premium>
    </coverage>
</value_pack>
<quote>
    <taxes_fees>
        <coverage source_id="55882d2cacb45">
            <name>mga_fee</name>
            <premium>25</premium>
        </coverage>
        <coverage source_id="55882d2cacb45">
            <name>citizens</name>
            <premium>165.65</premium>
        </coverage>
        <coverage source_id="55882d2cacb45">
            <name>empa</name>
            <premium>4</premium>
        </coverage>
        <coverage source_id="55882d2cacb45">
            <name>fire_surcharge</name>
            <premium>16.57</premium>
        </coverage>
    </taxes_fees>
</quote>

I need to find all the elements, regardless of name, that have a source_id attribute that matches the entry element's 'id' attribute (see first entry element) and process them individually. The value is unknown until runtime. Using a key seems to be part of the answer, but the element name seems to be hard-coded in all the examples I can find. Appreciate any insight!

Upvotes: 1

Views: 186

Answers (2)

Martin Honnen
Martin Honnen

Reputation: 167696

If you know about keys, you can use <xsl:key name="source" match="*[@source_id]" use="@source_id"/> to define the key for all elements having a source_id attribute. Then from <xsl:template match="entry"> you can use e.g. key('source', @id) to find all referenced elements or even in XSLT 2 key('source', @id, .) to find all referenced descendant elements of the entry

Upvotes: 0

kjhughes
kjhughes

Reputation: 111686

This XPath,

//*[@source_id = ancestor::entry/@id]

will select all elements with a source_id attribute value equal to an ancestor entry element's @id attribute value.

Upvotes: 1

Related Questions