如何通过XPath访问具有多个名称空间的XML元素?

时间:2012-09-04 09:29:46

标签: xml xslt xpath namespaces

我有一个看起来像这样的XML文件:

<?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>

另一方面,我有一个XSL文件来通过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>

有了这个我可以获取元素e2说我说但是我有问题要访问元素f4说早餐在Tiffany的。 XPath是否假设元素f4有两个名称空间(默认名称空间xmlns =“http://www.loc.gov/zing/srw/”在根元素中首先声明的命名空间element mods xmlns =“http://www.loc.gov/mods/v3”)或mods命名空间xmlns =“http://www.loc.gov/mods/v3”是所有childelements的唯一命名空间mods元素? 如果我的xsl文件中没有声明前缀,我是否可以更轻松地访问元素e2?我刚开始使用XML / XSL,所以我希望我的问题很明确。

2 个答案:

答案 0 :(得分:1)

以下XPath表达式应该有效:

n:first//o:f2

mods元素位于o命名空间中,定义其他命名空间的前缀不会更改它。它的子节点继承了命名空间。

答案 1 :(得分:1)

只是为了扩展choroba的答案 - 因为mod重置了默认的xmlns,你需要相应调整你的命名空间别名,即完整的步行是:

 <xsl:value-of select="/n:first/n:e3/n:e4/o:mods/o:f2/text()"/>

如果省略xslt中的命名空间,可以使用local-name()检查节点而不管它们的命名空间(在这种情况下不建议这样做,因为你可以看到,这变得非常冗长)

 <xsl:value-of select="/*[local-name()='first']/*[local-name()='e3']
                       /*[local-name()='e4']/*[local-name()='mods']
                       /*[local-name()='f2']/text()"/>

您可以将exclude-result-prefixes="n o"添加到xsl:stylesheet

,从输出文档(html)中删除别名

我建议不要养成使用'//'的习惯,因为解析器会对大型文档造成不必要的处理。