XSLT和默认命名空间的问题

时间:2014-02-06 17:59:10

标签: xml xslt xpath xhtml

我已经阅读了很多关于这个主题的其他问题,根据我在网站上其他地方读到的答案,我认为我正确地做了这个,但它仍然无效。

我有一个XHTML文件,我通过JTidy运行并运行XPath从该XHTML中选择一个表节点。一切正常,XPath能够很好地选择表,它返回以下XML片段:

<table xmlns="http://www.w3.org/1999/xhtml" align="left" border="1" cellpadding="3" cellspacing="3" id="ctl07_tblMain" rules="rows" style="border-color:Green; border-style:solid; border-width:1px;" summary="Table is for layout purpose only">
  <tr>
    <th class="GridViewHeader" colspan="19" style="font-weight:bold; text-align:center">Select an arrival date
to continue.</th>
  </tr>
  <tr class="altCampArea">
    <td align="center" width="400">Site Type</td>
    <td align="center"> Pet </td>
    <td align="center">Electric</td>
    <td align="center">Water</td>
    <td align="center">Sewer</td>
    <td align="center" title="Friday, 02/07/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/7/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/07</a>
    </td>
    <td align="center" title="Saturday, 02/08/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/8/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/08</a>
    </td>
    <td align="center" title="Sunday, 02/09/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/9/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/09</a>
    </td>
    <td align="center" title="Monday, 02/10/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/10/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/10</a>
    </td>
    <td align="center" title="Tuesday, 02/11/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/11/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/11</a>
    </td>
    <td align="center" title="Wednesday, 02/12/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/12/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/12</a>
    </td>
    <td align="center" title="Thursday, 02/13/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/13/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/13</a>
    </td>
    <td align="center" title="Friday, 02/14/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/14/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/14</a>
    </td>
    <td align="center" title="Saturday, 02/15/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/15/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/15</a>
    </td>
    <td align="center" title="Sunday, 02/16/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/16/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/16</a>
    </td>
    <td align="center" title="Monday, 02/17/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/17/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/17</a>
    </td>
    <td align="center" title="Tuesday, 02/18/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/18/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/18</a>
    </td>
    <td align="center" title="Wednesday, 02/19/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/19/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/19</a>
    </td>
    <td align="center" title="Thursday, 02/20/2014" width="20">
      <a href="#" onclick="javascript:closeAndRedirect(&quot;2/20/2014&quot;,&quot;SearchCriteria.aspx&quot;); return false;">02/20</a>
    </td>
  </tr>
  <tr>
    <td align="left" width="400">CEDAR GROVE-WATER ONLY CAMPSITE</td>
    <td align="center">Yes</td>
    <td align="center">No</td>
    <td align="center">Yes</td>
    <td align="center">No</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
    <td align="center">11</td>
  </tr>
  <tr class="altCampArea">
    <td align="left" width="400">LARGE TRAILER AREA-ELECTRIC &amp;
WATER CAMPSITE 50AMP</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">No</td>
    <td align="center">12</td>
    <td align="center">12</td>
    <td align="center">12</td>
    <td align="center">12</td>
    <td align="center">12</td>
    <td align="center">12</td>
    <td align="center">11</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">10</td>
    <td align="center">13</td>
    <td align="center">13</td>
    <td align="center">13</td>
    <td align="center">13</td>
  </tr>
  <tr>
    <td align="left" width="400">LARGE TRAILER
AREA-SEWER,ELECT&amp;WATER HOST 50AMP</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
  </tr>
  <tr class="altCampArea">
    <td align="left" width="400">OAK GROVE-SEWER,ELECT&amp;WATER
30AMP</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">2</td>
    <td align="center">3</td>
    <td align="center">3</td>
    <td align="center">3</td>
    <td align="center">3</td>
    <td align="center">3</td>
    <td align="center">3</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">2</td>
    <td align="center">2</td>
    <td align="center">2</td>
    <td align="center">3</td>
  </tr>
  <tr>
    <td align="left" width="400">PECAN GROVE-ELECTRIC &amp; WATER
CAMPSITE 20FT 50AMP</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">No</td>
    <td align="center">8</td>
    <td align="center">8</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
    <td align="center">9</td>
  </tr>
  <tr class="altCampArea">
    <td align="left" width="400">PECAN GROVE-ELECTRIC &amp; WATER
CAMPSITE 25FT 50AMP</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">No</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
    <td align="center">10</td>
  </tr>
  <tr>
    <td align="left" width="400">PECAN GROVE-ELECTRIC &amp; WATER TENT
ONLY 50AMP</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">No</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
  </tr>
  <tr class="altCampArea">
    <td align="left" width="400">PECAN GROVE-SEWER,ELECT&amp;WATER HOST
50AMP</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
  </tr>
  <tr>
    <td align="left" width="400">WAGON CIRCLE-GROUP TRAILER AREA
50AMP</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">No</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
    <td align="center">35</td>
  </tr>
  <tr class="altCampArea">
    <td align="left" width="400">WAGON CIRCLE-SEWER,ELECT&amp;WATER
PREMIUM 50AMP</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">Yes</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
    <td align="center">0</td>
  </tr>
</table>

然后我尝试使用这个XSLT处理它:

<xslt:stylesheet xmlns:xslt="http://www.w3.org/1999/XSL/Transform" xmlns:csw-xform="http://www.compositesw.com/2003/xform" xmlns:ns1="http://www.w3.org/1999/xhtml" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
  <xslt:template match="/">
    <xslt:variable name="_value"/>
    <xslt:element name="results">
      <xslt:for-each select="ns1:table">
        <xslt:for-each select="ns1:tr">
          <xslt:for-each select="ns1:td">
            <xslt:variable name="_value" select="normalize-space(.)"/>
            <xslt:element name="result">
              <xslt:element name="value">
                <xslt:value-of select="$_value"/>
              </xslt:element>
            </xslt:element>
          </xslt:for-each>
        </xslt:for-each>
      </xslt:for-each>
    </xslt:element>
  </xslt:template>
</xslt:stylesheet>

但是XSLT的结果只是:

<results/>

我怀疑这是一个命名空间问题,但据我所知,命名空间正在XSLT中正确处理。输入XML中的默认命名空间在XSLT中定义为“ns1”,并在该XSLT中的每个XPath表达式上使用。所以我因为我所缺少而感到茫然。

编辑2014-02-09:原来是我用来运行XSLT的软件平台中的一个错误。我上面粘贴的XML片段实际上只是一个较大文档的表格。为了抓住桌子我首先叫XPATH,就像这样:

DECLARE myXML LONGVARCHAR;
DECLARE myOutXML XML;
SET outXml = XPATH(myOutXML, '//*[@id=''ctl07_tblMain'']');

'outXml'被送入XSLT的地方。我不得不改变它以使其工作:

SET myOutXML = CAST(XPATH(myOutXML, '//*[@id=''ctl07_tblMain'']') AS LONGVARCHAR);
SET outXml = myOutXML;

出于某种原因,将XPATH的结果从XML转换为LONGVARCHAR,然后将其作为XML返回,修复了问题。

2 个答案:

答案 0 :(得分:0)

令您惊讶的是,我正在使用您的输入XML和XSLT获取输出。像这样:

<results>
<result>
    <value>Site Type</value>
</result>
<result>
    <value>Pet</value>
</result>
<result>
    <value>Electric</value>
</result>
.....

答案 1 :(得分:0)

这实际上与命名空间无关,因为它们看起来都是正确声明和引用的。

但是,我很惊讶你在运行XSLT时实际上并没有收到错误,因为你在模板中对同一个变量名有两个变量声明。首先...

<xslt:variable name="_value"/>

后来......

<xslt:variable name="_value" select="normalize-space(.)"/>

在同一模板中实际上不允许这样做。如果您没有意识到,XSLT中的变量是“不可变的”,这意味着一旦定义它们就无法更改。此外,您不需要“声明”它们并在以后“初始化”它们。

http://www.w3.org/TR/1999/PR-xslt-19991008#local-variables读取它所说的“如果由模板中的xsl:variable或xsl:param元素建立的绑定影响由xsl:variable建立的另一个绑定,则是错误的xsl:param元素也在模板中

我怀疑发生的事情是你的XSLT处理器没有通知你错误,只是没有执行错误发生的代码块。尝试删除第一个变量声明(实际设置 _value < / strong>为空字符串)。

话虽如此,您可以稍微简化一下XSLT。您不需要嵌套所有 xsl:for-each 语句,而是将它们合并为一个

<xslt:for-each select="ns1:table/ns1:tr/ns1:td"/>

甚至这个......

<xslt:for-each select=".//ns1:td"/>

更好的是,使用模板匹配!

<xslt:apply-templates select=".//ns1:td"/>

实际上,你根本不需要在这里声明任何变量。试试这个XSLT ....

<xslt:stylesheet xmlns:xslt="http://www.w3.org/1999/XSL/Transform"  xmlns:csw-xform="http://www.compositesw.com/2003/xform" xmlns:ns1="http://www.w3.org/1999/xhtml" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
  <xslt:template match="/">
    <xslt:element name="results">
      <xslt:apply-templates select=".//ns1:td"/>
    </xslt:element>
  </xslt:template>

  <xslt:template match="ns1:td">
      <xslt:element name="result">
      <xslt:element name="value">
        <xslt:value-of select="normalize-space(.)"/>
      </xslt:element>
    </xslt:element>
  </xslt:template>
</xslt:stylesheet>