jjzjj

xml - XSL 将具有属性的 xml 行转换为无序列表 TreeView

coder 2024-07-05 原文

我有以下来自 SharePoint 控件的 XML。我想使用 XSLT 进行转换以生成嵌套的 ul>li 列表。但是我在迭代每一行时遇到问题,主文件夹对每一行重复,而不是创建一个主文件夹节点并在该节点下添加 Menu_Display_name 的值以模拟 TreeView ... 我的 XML 是这样的:

<dsQueryResponse>
    <NewDataSet>
        <Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Create Timecard"></Row>
        <Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Recent Timecards"></Row>
        <Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Templates"></Row>
        <Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Timecard Search"></Row>
        <Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP EXP ENTRY" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Expenses Home"></Row>
        <Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Accommodation Request"></Row>
        <Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Additional Personal Information" ></Row>
        <Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="All Actions Awaiting Your Attention"></Row>
        <Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Appraisals"></Row>
    </NewDataSet>
</dsQueryResponse>

我对 XSL 的“穷人的尝试”是这样的:

 <xsl:template name="dvt_1.body">
    <xsl:param name="Rows" />
    <xsl:param name="FirstRow" />
    <xsl:param name="LastRow" />
    <ul>
      <xsl:for-each select="$Rows">
        <xsl:if test="position() &gt;= $FirstRow and position() &lt;= $LastRow">
          <xsl:call-template name="dvt_1.rowview" />
        </xsl:if>
      </xsl:for-each>
    </ul>
  </xsl:template>


  <xsl:template name="dvt_1.rowview">

    <li class="isFolder isExpanded">
       <xsl:value-of select="@PRIMARY_FOLDER" />
       <xsl:choose>
         <xsl:when test="@SECONDARY_FOLDER != ''">
           <ul>
             <li class="isFolder isExpanded">
               <xsl:value-of select="@SECONDARY_FOLDER" />
               <ul>
                  <li><xsl:value-of select="@MENU_DISPLAY_NAME" /></li>
               </ul>
             </li>
           </ul>
         </xsl:when>
         <xsl:otherwise>
           <ul>
              <li><xsl:value-of select="@MENU_DISPLAY_NAME" /></li>
           </ul>
          </xsl:otherwise>
        </xsl:choose>
    </li>

  </xsl:template>

我想要的 xsl 输出是这样的:

<div id="navigator">
        <ul>
            <li class="isFolder isExpanded">
               XYZ CORP HR TIME SELF SERVICE    
                <ul>
                    <li class="isFolder isExpanded">
                        Time
                            <ul>
                                <li><a href="#" target="_tab">Create Timecard</a></li>
                                <li><a href="#" target="_tab">Recent Timecards</a></li>
                                <li><a href="#" target="_tab">Templates</a></li>
                                <li><a href="#" target="_tab">Timecard Search</a></li>                                   
                            </ul>
                    </li>
                </ul>        
            </li>
            <li class="isFolder isExpanded">
                XYZ CORP EXP ENTRY
                <ul>
                    <li><a href="#" target="_tab">Expense Home</a></li>      
                </ul>
            </li> 
            <li class="isFolder isExpanded">
                XYZ HR EMP SELF SERVICE
                <ul>
                    <li><a href="#" target="_tab">Accommodation Request</a></li>
                    <li><a href="#" target="_tab">Additional Personal Information</a></li>
                    <li><a href="#" target="_tab">All Actions Awaiting Your Attention</a></li>
                    <li><a href="#" target="_tab">Appraisals</a></li>
                </ul>
            </li>
        </ul>
    </div>

有人可以帮我用 xslt 实现这个吗?

最佳答案

Muenchian grouping确实是您需要在 XSLT 1.0 中查看的内容(我相信这是 Sharepoint 使用的内容)。首先你按 PRIMARY_VALUE 属性分组,所以你有一个像这样的键:

<xsl:key name="primary" match="Row" use="@PRIMARY_FOLDER" />

但我假设对于给定的 PRIMARY_VALUE,您可能有多个 SECONDARY_FOLDER,因此您需要第二个 key :

<xsl:key name="secondary" match="Row" use="concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER)" />

首先选择每个 PRIMARY_FOLDER 值第一次出现的行

<xsl:for-each select="$rows[generate-id() = generate-id(key('primary', @PRIMARY_FOLDER)[1])]">

然后在此范围内,您选择具有不同 SECONDARY_VALUE 的行以构成嵌套列表的基础

<xsl:apply-templates select="key('primary', @PRIMARY_FOLDER)[generate-id() = generate-id(key('secondary', concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER))[1])]" mode="secondary" />

唯一的额外工作是,根据 SECONDARY_FOLDER 是否被填充,您的行为会略有不同。不过,您可以使用两个单独的模板来完成此操作。

试试这个 XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html" indent="yes" />

    <xsl:key name="primary" match="Row" use="@PRIMARY_FOLDER" />
    <xsl:key name="secondary" match="Row" use="concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER)" />

    <xsl:variable name="rows" select="//Row" />

    <xsl:template match="/">
      <ul>
          <xsl:for-each select="$rows[generate-id() = generate-id(key('primary', @PRIMARY_FOLDER)[1])]">
              <li class="isFolder isExpanded">
                  <xsl:value-of select="@PRIMARY_FOLDER" />
                  <xsl:apply-templates select="key('primary', @PRIMARY_FOLDER)[generate-id() = generate-id(key('secondary', concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER))[1])]" mode="secondary" />
              </li>
          </xsl:for-each>
      </ul>
    </xsl:template>

    <xsl:template match="Row[@SECONDARY_FOLDER != '']" mode="secondary">
        <li class="isFolder isExpanded">
            <xsl:value-of select="@SECONDARY_FOLDER" />
            <ul>
                <xsl:apply-templates select="key('secondary', concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER))" />
            </ul>
        </li>
    </xsl:template>

    <xsl:template match="Row" mode="secondary">
        <xsl:apply-templates select="key('primary', @PRIMARY_FOLDER)" />
    </xsl:template>

    <xsl:template match="Row">
        <li>
            <a href="#" target="_tab">
                <xsl:value-of select="@MENU_DISPLAY_NAME" />
            </a>
        </li>
    </xsl:template>
</xsl:stylesheet>

请参阅 http://xsltransform.net/pPzifq9 中的实际操作.

请注意,如果您的实际 XML 具有 namespace ,则您需要修改 XSLT 以将这些考虑在内。

关于xml - XSL 将具有属性的 xml 行转换为无序列表 TreeView ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35921339/

有关xml - XSL 将具有属性的 xml 行转换为无序列表 TreeView的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  2. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  3. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  5. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  6. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  7. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  8. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  9. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  10. ruby-on-rails - Rails 3.1 中具有相同形式的多个模型? - 2

    我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#

随机推荐