I am working on a project who has thus far relied on setting:
DocumentBuilderFactory.setNamespaceAware(false);
To achieve namespace flexible xpaths (that ignore whatever prefix may be passed in).
This only worked in the past because the xalan transformer was being used and although technically the behavior of setting namespace aware to false should be undefined at best, for the given xml, xalan treats the following xpath as valid.
xml:
<t:GiftBasket xmlns:t="http://tastyTreats.com/giftbasket">
<t:Fruit>
<t:Apple>
<t:Name>Cameo</t:Name>
<t:Color>Red</t:Color>
<t:TasteDescription>Juicy, crisp, and sweet with just a touch of tart, the Cameo is thought to come from both the Red and the Yellow Delicious.</t:TasteDescription>
</t:Apple>
<t:Apple>
<t:Name>Empire</t:Name>
<t:Color>Red</t:Color>
<t:TasteDescription>The interior is crisp and creamy white while being firmer than the McIntosh, so it makes for a good cooking apple. </t:TasteDescription>
</t:Apple>
<t:Apple>
<t:Name>Granny Smith</t:Name>
<t:Color>Green</t:Color>
<t:TasteDescription>Hard feel, crisp bite, and extremely tart taste. Some prefer to cook it, which sweetens it up.</t:TasteDescription>
</t:Apple>
</t:Fruit>
<t:Candy>
<t:Chocolate>Dark</t:Chocolate>
</t:Candy>
</t:GiftBasket>
xpath:
/GiftBasket/Fruit/Apple[Color='Red'][contains(TasteDescription,'sweet')]
In switching over to xslt 2.0 I switched to the Saxon-HE transformer. Saxon is a more exact transformer (good thing IMO). It recognizes that these xpath expressions are "wrong" and I now have to fix a bunch of xpath expressions like the above to work regardless of namespace prefix referenced (client may choose to prefix the URI http://tastyTreats.com/giftbasket as 'fluffybunnies' for all i know)
I have received other good counsel here on how to utilize the local-name()
function to achieve most of what I need. My xpath now reads:
/*[local-name()='GiftBasket']/*[local-name()='Fruit']/*[local-name()='Apple'][Color='Red'][contains(TasteDescription,'sweet')]
This is still not accurate, however, as the elements referenced in the predicates are still referencing exact element names Color
and TasteDescription
without being namespace flexible. Is there a better way to write an xpath for all the red apples that contain 'sweet' in their taste description while remaining namespace prefix flexible?