如何使用XSLT转换选择XML中的特定节点或元素?

如何使用XSLT转换选择XML中的特定节点或元素?,xml,xslt,Xml,Xslt,我的XML是 <row> <entry>1.</entry> <entry>foo</entry> <entry>morefoo</entry> </row> <row> <entry>2.</entry> <entry>2foo</entry> <entry>2morefoo</entry>

我的XML是

<row>
  <entry>1.</entry>
  <entry>foo</entry>
  <entry>morefoo</entry>
</row>
<row>
  <entry>2.</entry>
  <entry>2foo</entry>
  <entry>2morefoo</entry>
</row>
<row> 
<entry>1.</entry> 
<entry>foo</entry> 
<entry>morefoo</entry> 
</row> 
<row> 
<entry>2.</entry> 
<entry>2foo</entry> 
<entry>2morefoo</entry> 
</row>

1.
福
莫雷福
2.
2foo
2莫雷福
使用XSLT,我试图在html表中表示这些信息,我希望有一个序列号列

如何仅选择第一个“entry”标记的值

//row/entry[1]
这将选择父节点的第一个子节点的所有
条目
标记

我的XML是

<row>
  <entry>1.</entry>
  <entry>foo</entry>
  <entry>morefoo</entry>
</row>
<row>
  <entry>2.</entry>
  <entry>2foo</entry>
  <entry>2morefoo</entry>
</row>
<row> 
<entry>1.</entry> 
<entry>foo</entry> 
<entry>morefoo</entry> 
</row> 
<row> 
<entry>2.</entry> 
<entry>2foo</entry> 
<entry>2morefoo</entry> 
</row>
上面选择每个
元素的第一个
条目
元素子元素

/*/row[1]/entry[1]
上面选择文档中第一个
元素的第一个
条目
元素子元素

/*/row[2]/entry[1]
(//entry)[1]
//entry[1]
上面选择文档中第二行元素的第一个条目元素子元素

/*/row[2]/entry[1]
(//entry)[1]
//entry[1]
上面选择整个文档中的第一个
条目
元素

/*/row[2]/entry[1]
(//entry)[1]
//entry[1]

请注意,这与前面的表达式不同:它选择文档中的每个
条目
元素,这是其父项的第一个
条目
-子项。

下面的XSLT将生成此表:

Serial No Name Description 1. foo morefoo 2. 2foo 2morefoo 序列号名称说明 1.福摩福 2.2foo 2morefoo 示例文档:

<?xml version="1.0" encoding="utf-8"?>
<document>
  <row>
    <entry>1.</entry>
    <entry>foo</entry>
    <entry>morefoo</entry>
  </row>
  <row>
    <entry>2.</entry>
    <entry>2foo</entry>
    <entry>2morefoo</entry>
  </row>
</document>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>Sample</title>
      </head>
      <body>
        <table border="1">
          <tr>
            <th>Serial No</th>
            <th>Name</th>
            <th>Description</th>
          </tr>
          <xsl:apply-templates />
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="row">
    <tr>
      <xsl:for-each select="entry">
        <td>
          <xsl:value-of select="."/>
        </td>
      </xsl:for-each>
    </tr>
  </xsl:template>

</xsl:stylesheet>

1.
福
莫雷福
2.
2foo
2莫雷福
XSLT:

<?xml version="1.0" encoding="utf-8"?>
<document>
  <row>
    <entry>1.</entry>
    <entry>foo</entry>
    <entry>morefoo</entry>
  </row>
  <row>
    <entry>2.</entry>
    <entry>2foo</entry>
    <entry>2morefoo</entry>
  </row>
</document>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>Sample</title>
      </head>
      <body>
        <table border="1">
          <tr>
            <th>Serial No</th>
            <th>Name</th>
            <th>Description</th>
          </tr>
          <xsl:apply-templates />
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="row">
    <tr>
      <xsl:for-each select="entry">
        <td>
          <xsl:value-of select="."/>
        </td>
      </xsl:for-each>
    </tr>
  </xsl:template>

</xsl:stylesheet>

样品
序列号
名称
描述

在XSLT中,应该有如下内容:

<!-- matches the root (not specified in your post) -->
<xsl:template match="/">
   <!-- at root level, make your table -->
   <table>
     <thead>.... </thead>
     <tbody>
       <!-- push the rows through, make sure the path is correct -->
       <xsl:apply-templates select="path/to/row" />
     </tbody>
   </table>
</xsl:template>

<xsl:template match="row">
   <!-- create the rows -->
   <tr>
     <!-- process first entry only, as you requested (why?) -->
     <xsl:apply-templates select="entry[1]" mode="first"/>
     <!-- process other entries -->
     <xsl:apply-templates select="entry[position() > 1]" mode="other"/>
   </tr>
</xsl:template>

<xsl:template match="entry" mode="first">
   <!-- maybe you want the first cell to be treated specially, i.e. as row header -->
   <th><xsl:value-of select="."/></th>
</xsl:template>

<xsl:template match="entry" mode="other">
   <!-- the other cells -->
   <td><xsl:value-of select="."/></td>
</xsl:template>

.... 
注意:上面的代码未经测试,请将其用作您自己真实代码和数据的模板

输出如下所示:

<table>
  <thead>....</thead>
  <tbody>
    <tr>
      <th>1.</th>
      <td>foo</td>
      <td>morefoo</td>
    </tr>
    <tr>
      <th>2.</th>
      <td>2foo</td>
      <td>2morefoo</td>
    </tr>
    <tr>....
  </tbody>
</table>

....
1.
福
莫雷福
2.
2foo
2莫雷福
....

你能发布一个应该制作的表格样本吗?好问题(+1)。有关提供所需功能的许多XPath表达式,请参见我的答案,有关不同XPath风格的解释,请参见更多…+1。如果@charudatta也感兴趣的话,它包含了XPath表达式的每一个细节。+1来自我,但可能会提出一个问题:为什么要使用
(//entry)[1]
而不仅仅是
//entry[1]
?@Abel:
(//entry)[1]
呢,我只是想说明一点,如果这增加了混乱,我很抱歉;)@亚伯:没问题,我在回答中添加了最后一个表达,没有详细解释。+1是一个很好的工作示例(而且你比我快;-)。但我不会选择for each,在这种情况下,区分第一个单元格和其他单元格会(稍微)困难一些。回答得好!但是,我认为,如果有更多的“模式匹配”(如
match=“entry[1]”
)和不使用apply templates/@select,这将是一个更好的例子。。。它最好是将
转换为
TR
,将
条目
转换为
TD