【问题标题】:xsl and XML transform producing duplicate recordsxsl 和 XML 转换产生重复记录
【发布时间】:2012-08-02 03:36:20
【问题描述】:

我收到以下 xml 和 xsl 文件的重复记录。我只想转换一组列表项。如果可能,尽量不要从 xsl 部分删除任何内容(只需添加即可)。

<?xml version="1.0" encoding="utf-8" ?>
<data>
  <listitems name="Select..." CtrId="Id2"/>
  <listitems name="Item A" CtrId="Id2"/>
  <listitems name="Item B" CtrId="Id2"/>
  <listitems name="Select..." CtrId="Id4"/>
  <listitems name="Item A" CtrId="Id4"/>
  <listitems name="Item B" CtrId="Id4"/>  
  <listitems name="Select..." CtrId="Id6"/>
  <listitems name="Item C" CtrId="Id6"/>
  <listitems name="Item D" CtrId="Id6"/>  
</data>

 

  <xsl:template match="data/listitems">
    <html>
      <head>
        <title>Untitled</title>
      </head>
      <body>
        <xsl:value-of select="@name"/>
      </body>
    </html>
  </xsl:template>

 

结果(不正确的行为;重复) 选择... 项目 A 项目 B 选择... 项目 A 项目 B

期望的行为(仅获得 1 组) 选择... 项目 A 项目 B

【问题讨论】:

  • 我倾向于认为您的 XML 设计不佳。我不知道您是否可以控制它,但如果可以,我建议您将&lt;Ctr Id="Id2"&gt; 元素作为&lt;data&gt; 的子元素放入,并将&lt;listitems name="Select..."&gt; 放入其中,等等。通常任何属于一个组应该包含在代表该组的元素中。在这样的组上运行的任何 XSLT 都会容易得多。
  • 有没有可以抓取第一组相同的CtrlId?
  • 是的,这是一个很好的例子——这对于我建议的设计来说是微不足道的。

标签: c# asp.net xslt


【解决方案1】:

这是一个相对简单的方法:

<xsl:param name="useId" select="/data/listitems[1]/@CtrId" />

<xsl:template match="/">
  <html>
    <head>
      <title>Untitled</title>
    </head>
    <body>
      <xsl:apply-templates select="data/listitems[@CtrId = $useId]"/>
    </body>
  </html>
</xsl:template>

<xsl:template match="listitems">
  <xsl:value-of select="concat(@name, ' ')" />
</xsl:template>

您现有的模板实际上会为每个 listitems 元素添加一个 html 元素 - 您似乎很可能只想要一个。

顶部的&lt;xsl:param&gt; 声明选择文件中的第一个 CtrId,并使用它。您可以使用 select="'Id2'" 将其更改为文字值(注意双引号内的单引号),或者您可以将参数传递到样式表中,并使用您要选择的 ID。

【讨论】:

    【解决方案2】:

    这种转变

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
      <xsl:template match="/*">
        <html>
          <head>
            <title>Untitled</title>
          </head>
          <body>
           <xsl:apply-templates select=
              "*[starts-with(@name,'Select')][1]"/>
          </body>
        </html>
      </xsl:template>
    
      <xsl:template match="*[starts-with(@name,'Select')]">
        <xsl:apply-templates mode="inGroup" select=
        "(.|following-sibling::*
            [generate-id(following-sibling::*
                         [@name[starts-with(.,'Select')]][1]
                         )
            =
             generate-id(current()/following-sibling::*
                                   [@name[starts-with(.,'Select')]][1])
            ]
         )/@name
        "/>
      </xsl:template>
    
      <xsl:template match="@name" mode="inGroup">
       <xsl:value-of select="concat(., ' ')"/>
      </xsl:template>
    </xsl:stylesheet>
    

    应用于提供的 XML 文档时

    <data>
      <listitems name="Select..." CtrId="Id2"/>
      <listitems name="Item A" CtrId="Id2"/>
      <listitems name="Item B" CtrId="Id2"/>
      <listitems name="Select..." CtrId="Id4"/>
      <listitems name="Item A" CtrId="Id4"/>
      <listitems name="Item B" CtrId="Id4"/>
    </data>
    

    产生想要的正确结果:

    <html>
       <head>
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    
          <title>Untitled</title>
       </head>
       <body>Select... Item A Item B </body>
    </html>
    

    【讨论】:

    • 感谢您的反馈...我对 XSL 很陌生。你能给新手提供一些见解吗?例如,一些符号如 .|following-sibling::* 和 generate-id 和 mode="inGroup"?
    • @rod:这些被称为“XPath 表达式”。大多数 XSLT 指令对选择特定节点集的 XPath 表达式进行操作。一个答案无法提供有关 XPath 和 XSLT 主题的所有重要信息。请阅读一本好的 XPath 和 XSLT 书籍以了解 XSLT。你可以在这里找到一些很好的资源:@​​987654321@
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-31
    • 1970-01-01
    • 2017-02-06
    相关资源
    最近更新 更多