2015-01-05 77 views
0

我想将唯一的XML子元素值添加到选择列表。以下是我迄今为止将唯一的XML元素值添加到选择列表

XML:

<Student> 
    <record> 
    <Name>Jack</Name> 
    </record> 
    <record> 
    <Name>Jack</Name> 
    </record> 
    <record> 
    <Name>John</Name> 
    </record> 
    <record> 
    <Name>John</Name> 
    </record> 
    <record> 
    <Name>John</Name> 
    </record> 
    <record> 
    <Name>Jill</Name> 
    </record> 
    <record> 
    <Name>Jill</Name> 
    </record> 
    <record> 
    <Name>James</Name> 
    </record> 
</Student> 

XSLT:

<xsl:key name="NameKey" match="Name" use="."/> 

    <xsl:template match="Student"> 
    <table> 
     <tr> 
     <th>Name</th> 
     <td> 
      <select> 
       <xsl:for-each select="record"> 
       <option> 
       <xsl:element name="Name"> 
        <xsl:value-of select="Name[generate-id() = generate-id(key('NameKey',.)[1])]" /> 
       </xsl:element> 
       </option> 
       </xsl:for-each>    
      </select> 
     </td> 
     </tr> 
     <xsl:apply-templates select="/record" /> 
    </table> 
    </xsl:template> 
</xsl:stylesheet> 

我成功获得唯一值列表,但名单还显示为空字符串列表中的非唯一值。所以我的名单有以下值:

Jack 

John 


Jill 

James 

有没有什么办法摆脱列表中的那些空字符串值?

+0

请向我们展示一个XML输入示例,以便我们可以重现该问题。 - P.S.我没有看到你正在收集**属性**值; *属性*这个词在XML中具有非常精确的含义。 –

+0

@ michael.hor257k我已更新我的问题。对不起,我错了,我的意思是元素值 – user793468

回答

1

有什么办法摆脱列表中的空字符串值?

是的,只需将键名查找的谓词移动到xsl:for-each即可。使用您当前的代码,全部这些节点将交给xsl:for-each,包括重复项。

顺便说一句,这条线

<xsl:apply-templates select="/record" /> 

不会做任何事情,因为最外层的元素节点不叫record。你在这里有什么意图?

XSLT样式表

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

    <xsl:output method="html" encoding="UTF-8" indent="yes" /> 
    <xsl:key name="NameKey" match="Name" use="."/> 

    <xsl:template match="Student"> 
    <table> 
     <tr> 
     <th>Name</th> 
     <td> 
      <select> 
       <xsl:for-each select="record/Name[generate-id() = generate-id(key('NameKey',.)[1])]"> 
       <option> 
       <xsl:element name="Name"> 
        <xsl:value-of select="." /> 
       </xsl:element> 
       </option> 
       </xsl:for-each>    
      </select> 
     </td> 
     </tr> 
     <xsl:apply-templates select="/record" /> 
    </table> 
    </xsl:template> 
</xsl:stylesheet> 

HTML输出

<table> 
    <tr> 
     <th>Name</th> 
     <td> 
     <select> 
      <option> 
       <Name>Jack</Name> 
      </option> 
      <option> 
       <Name>John</Name> 
      </option> 
      <option> 
       <Name>Jill</Name> 
      </option> 
      <option> 
       <Name>James</Name> 
      </option> 
     </select> 
     </td> 
    </tr> 
</table> 

呈现的HTML

enter image description here

+0

谢谢!我删除了“”行 – user793468

1

我想补充一点,这也可以通过使用[not(.=preceding::*)]来实现。

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

    <xsl:output method="html" encoding="UTF-8" indent="yes" /> 

    <xsl:template match="Student"> 
     <table> 
      <tr> 
       <th>Name</th> 
       <td> 
        <select> 
         <xsl:for-each select="record/Name[not(.=preceding::*)]"> 
          <option> 
           <xsl:element name="Name"> 
            <xsl:value-of select="." /> 
           </xsl:element> 
          </option> 
         </xsl:for-each>    
        </select> 
       </td> 
      </tr> 
      <xsl:apply-templates select="/record" /> 
     </table> 
    </xsl:template> 
</xsl:stylesheet> 

我个人认为这样更清楚你只处理每个Name元素一次。

+0

这不是一个好方法 - 请看这里why:http://www.jenitennison.com/xslt/grouping/muenchian.html –