Reputation: 25
I've got an XML file which looks somehow like this:
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type="text/xsl" href="http://url/stylesheet.xsl"?>
<first xmlns="http://www.loc.gov/zing/srw/">
<element1>And</element1>
<e2>I said</e2>
<e3>
<e4>
<mods version="3.0"
xmlns:bla="http://www.w3.org/1999/xlink"
xmlns:bla2="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.loc.gov/mods/v3"
xsi:schemaLocation="http://www.loc.gov/mods/v3">
<f1>What about</f1>
<f2>Breakfast at Tiffany's</f2>
</mods>
</e4>
</e3>
</first>
On the other hand I have an XSL-file to grab the elements via XPath:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:n="http://www.loc.gov/zing/srw/"
xmlns:o="http://www.loc.gov/mods/v3">
<xsl:template match="/">
<html><head></head><body>
<xsl:value-of select="n:first/n:e2"/>
</body></html>
</xsl:template>
</xsl:stylesheet>
With this I can fetch the element e2 saying I said but I have problems to access element f4 saying Breakfast at Tiffany's . Does XPath assume that the element f4 has two namespaces (the default namespace xmlns="http://www.loc.gov/zing/srw/" declared in the root element first and the namespace of the element mods xmlns="http://www.loc.gov/mods/v3") or is the mods namespace xmlns="http://www.loc.gov/mods/v3" the only namespace for all childelements of the mods element? And can I actually access the element e2 easier without the declaration of prefixes in my xsl-file? I am just starting to use XML/XSL, so I hope my question is clear.
Upvotes: 1
Views: 1726
Reputation: 107237
Just to expand on choroba's answer - because mod
resets the default xmlns
, you will need to adapt your namespace alias accordingly, i.e. the full walk is:
<xsl:value-of select="/n:first/n:e3/n:e4/o:mods/o:f2/text()"/>
If you omit the namespaces in your xslt, you can use local-name()
to check for nodes irrespective of their namespace (which is not recommended in this case, since as you can see, this becomes very verbose)
<xsl:value-of select="/*[local-name()='first']/*[local-name()='e3']
/*[local-name()='e4']/*[local-name()='mods']
/*[local-name()='f2']/text()"/>
You can remove the aliases from the output document (html) by adding exclude-result-prefixes="n o"
to your xsl:stylesheet
I would advise against getting into the habit of using '//' as can cause unnecessary processing by the parser on large documents.
Upvotes: 1
Reputation: 241738
The following XPath expression should work:
n:first//o:f2
The mods
element is in the o
namespace, defining prefixes for other namespaces does not change it. Its children inherit the namespace.
Upvotes: 1