错误:前缀必须解析为命名空间

时间:2015-07-05 12:36:01

标签: xml xslt

我想要通过XSLT转换以下XML。 我的主要目的是仅列出网址列表。它表示包含“http://”的任何行。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<urlset xmlns="http://www.google.com" xmlns:image="http://www.google1.com" xmlns:video="http://www.google2.com" xmlns:xhtml="http://www.google3.com">
  <url>
    <loc id="837">http://url1</loc>
  </url>
  <url>
    <loc id="2332">http://url2</loc>
    <image:image>
      <image:loc>http://url3</image:loc>
    </image:image>
    <image:image>
      <image:loc>http://url4</image:loc>
    </image:image>    
  </url>
</urlset>

我创建了一个XSLT,如下所示;

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml"
  doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
  doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

    <xsl:template match="/">
        <html>
            <body>
                <h1>URLS</h1>
               <ul>                    
                 <xsl:for-each select="urlset/url">
                    <li>
                        <xsl:value-of select="loc"/>
                    </li>
                 </xsl:for-each>
                  <xsl:for-each select="urlset/url/image:image">
                    <li>
                        <xsl:value-of select="image:loc"/>
                    </li>
                 </xsl:for-each>
               </ul>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet> 

第一个foreach没有返回任何东西 第二个foreach给出了例外:

  

SystemId未知;第15行;第53栏;前缀必须解析为a   namespace:image

有人可以帮助解决这个XSLT失败的原因吗?

2 个答案:

答案 0 :(得分:6)

要解决即时错误,请在样式表中添加image命名空间前缀的命名空间定义:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:image="http://www.google.com">

消除该错误后,还需要进行许多其他调整。在XML中为同一个(可疑的)命名空间定义这么多名称空间前缀是没有意义的。

以下输入XML之类的内容会更合理:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<urlset xmlns="http://www.example.com/urlset"
        xmlns:image="http://www.example.com/image">
  <url>
    <loc id="837">url1</loc>
  </url>
  <url>
    <loc id="2332">url2</loc>
    <image:image>
      <image:loc>url3</image:loc>
    </image:image>
    <image:image>
      <image:loc>url4</image:loc>
    </image:image>    
  </url>
</urlset>

然后,以下XSLT,

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
                xmlns:u="http://www.example.com/urlset"
                xmlns:image="http://www.example.com/image"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/u:urlset">
    <html>
      <body>
        <h1>URLS</h1>
        <ul>                    
          <xsl:for-each select="u:url">
            <li>
              <xsl:value-of select="u:loc"/>
            </li>
          </xsl:for-each>
          <xsl:for-each select="u:url/image:image">
            <li>
              <xsl:value-of select="image:loc"/>
            </li>
          </xsl:for-each>
        </ul>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet> 

将生成您寻找的URL列表:

<html xmlns:u="http://www.example.com/urlset" xmlns:image="http://www.example.com/image">
   <body>
      <h1>URLS</h1>
      <ul>
         <li>url1</li>
         <li>url2</li>
         <li>url3</li>
         <li>url4</li>
      </ul>
   </body>
</html>

您还可以考虑使用基于模板匹配的XSLT组织而不是基于循环的组织作为样式。对于像这样的小例子,复杂性差别不大,但对于更大的问题,基于匹配的组织更清晰,更清晰。

答案 1 :(得分:2)

您的XML似乎可以有三种loc元素,每个元素位于不同的命名空间中。要获得所有这些,你需要做这样的事情:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:g="http://www.google.com" 
xmlns:image="http://www.google1.com" 
xmlns:video="http://www.google2.com"
exclude-result-prefixes="g image video">

<xsl:template match="/g:urlset">
    <html>
        <body>
            <h1>URLS</h1>
            <ul>                    
                <xsl:for-each select="g:url/g:loc | g:url/image:image/image:loc | g:url/video:video/video:loc">
                    <li>
                        <xsl:value-of select="."/>
                    </li>
                 </xsl:for-each>
            </ul>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>

测试输入

<urlset xmlns="http://www.google.com" xmlns:image="http://www.google1.com" xmlns:video="http://www.google2.com">
  <url>
    <loc id="123">http://urll</loc>
  </url>
  <url>
    <loc id="456">http://url2</loc>
    <image:image>
      <image:loc>http://url3</image:loc>
    </image:image>
  </url>
  <url>
    <loc id="789">http://url4</loc>
    <video:video>
      <video:loc>http://url5</video:loc>
    </video:video>
  </url>
</urlset>

<强>结果

<html>
   <body>
      <h1>URLS</h1>
      <ul>
         <li>http://urll</li>
         <li>http://url2</li>
         <li>http://url3</li>
         <li>http://url4</li>
         <li>http://url5</li>
      </ul>
   </body>
</html>

一种简单但效率较低的替代方案:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
    <html>
        <body>
            <h1>URLS</h1>
            <ul>                    
                <xsl:for-each select="//*[local-name()='loc']">
                    <li>
                        <xsl:value-of select="."/>
                    </li>
                 </xsl:for-each>
            </ul>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>