How to organize entries of XML

后端 未结 2 1393
遇见更好的自我
遇见更好的自我 2021-01-26 00:58

XML:



    

        
相关标签:
2条回答
  • 2021-01-26 01:37

    Given the following input:

    XML

    <root>
        <tfLink01>Link #2</tfLink01>
        <mOrder>2</mOrder>
        <tfText01 />
        <cfSM1>false</cfSM1>
        <tf1SLink01 />
        <tf1SText01 />
        <tf2SLink01 />
        <tf2SText01 />
        <tf3SLink01 />
        <tf3SText01 />
    
        <tfLink02>Link #1</tfLink02>
        <mOrder>1</mOrder>
        <tfText02 />
        <cfSM2>false</cfSM2>
        <tf1SLink02 />
        <tf1SText02 />
        <tf2SLink02 />
        <tf2SText02 />
        <tf3SLink02 />
        <tf3SText02 />
    
        <tfLink03>Link #3</tfLink03>
        <mOrder>3</mOrder>
        <tfText03 />
        <cfSM3>false</cfSM3>
        <tf1SLink03 />
        <tf1SText03 />
        <tf2SLink03 />
        <tf2SText03 />
        <tf3SLink03 />
        <tf3SText03 />
    </root>
    

    the following stylehseet:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
    
    <xsl:template match="/root">
        <ul>
            <xsl:for-each select="mOrder">
                <xsl:sort/>
                <li>
                    <xsl:value-of select="preceding-sibling::*[1]"/>
                </li>
            </xsl:for-each>
        </ul>
    </xsl:template>
    
    </xsl:stylesheet>
    

    will return:

    <ul>
      <li>Link #1</li>
      <li>Link #2</li>
      <li>Link #3</li>
    </ul>
    

    Note:

    You can capture the ordinal number in a variable, for example:

    <xsl:variable name="ordinal" select="substring-after(name(preceding-sibling::*[1]), 'tfLink')" />
    

    and use it to address additional nodes by their name, instead of by their position in the "block".


    Added:

    For an input where the mOrder nodes are also numbered, i.e.:

    XML

    <root>
        <tfLink01>Link #2</tfLink01>
        <mOrder1>2</mOrder1>
        <tfText01 />
        <cfSM1>false</cfSM1>
        <tf1SLink01 />
        <tf1SText01 />
        <tf2SLink01 />
        <tf2SText01 />
        <tf3SLink01 />
        <tf3SText01 />
    
        <tfLink02>Link #1</tfLink02>
        <mOrder2>1</mOrder2>
        <tfText02 />
        <cfSM2>false</cfSM2>
        <tf1SLink02 />
        <tf1SText02 />
        <tf2SLink02 />
        <tf2SText02 />
        <tf3SLink02 />
        <tf3SText02 />
    
        <tfLink03>Link #3</tfLink03>
        <mOrder3>3</mOrder3>
        <tfText03 />
        <cfSM3>false</cfSM3>
        <tf1SLink03 />
        <tf1SText03 />
        <tf2SLink03 />
        <tf2SText03 />
        <tf3SLink03 />
        <tf3SText03 />
    </root>
    

    you can use:

    <xsl:template match="/root">
        <ul>
            <xsl:for-each select="*[starts-with(name(), 'tfLink')]">
                <xsl:sort select="following-sibling::*[1]"/>
                <li>
                    <xsl:value-of select="."/>
                </li>
            </xsl:for-each>
        </ul>
    </xsl:template>
    
    0 讨论(0)
  • 2021-01-26 01:47

    It is better if you structure your XML like this (omitted unused fields for brevity):

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <grp>
        <tfLink>Link #2</tfLink>
        <mOrder>2</mOrder>
      </grp>
      <grp>
        <tfLink>Link #1</tfLink>
        <mOrder>1</mOrder>
      </grp>
      <grp>
        <tfLink>Link #3</tfLink>
        <mOrder>3</mOrder>
      </grp>
    </root>
    

    Your XSLT then becomes:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
      <xsl:template match="/root">
        <div class="hidOverflow vertAlignT setCenter smallPadBottom">
          <div id="dvExpProvHolder" class="hidOverflow innerDivCenter">
            <ul class="uSPStyle" id="uSPStyle">
    
              <xsl:for-each select="grp">
                <xsl:sort select="mOrder" />
                <li>
                  <a class="tfLink clickMe" title="{tfLink}"  href="javascript:void(0);"
                     data-toggle='collapse' data-target="#{generate-id()}">
                    <xsl:value-of select="tfLink" />
                  </a>
                </li>
              </xsl:for-each>
    
            </ul>
          </div>
        </div>
      </xsl:template>
    </xsl:stylesheet>
    

    I've also modified the data-toggle (I assume it's Bootstrap) to name the class it should toggle (collapse as an example), and the data-target to use generate-id(), which you should use when generating the content to be acted upon.

    The XML resulting from the above is this:

    <?xml version="1.0"?>
    <div class="hidOverflow vertAlignT setCenter smallPadBottom">
      <div id="dvExpProvHolder" class="hidOverflow innerDivCenter">
        <ul class="uSPStyle" id="uSPStyle">
          <li>
            <a class="tfLink clickMe" title="Link #1" data-toggle="collapse" data-target="#idp31396560" href="javascript:void(0);">Link #1</a>
          </li>
          <li>
            <a class="tfLink clickMe" title="Link #2" data-toggle="collapse" data-target="#idp31377232" href="javascript:void(0);">Link #2</a>
          </li>
          <li>
            <a class="tfLink clickMe" title="Link #3" data-toggle="collapse" data-target="#idp31398000" href="javascript:void(0);">Link #3</a>
          </li>
        </ul>
      </div>
    </div>
    

    If you need to set attributes on the first element in the xsl:for-each, you can use this in the XSLT:

    <xsl:for-each ...>
        <xsl:sort .../>
        <li>
          <xsl:if test="position()=1">
            <xsl:attribute name="class">setCurrent</xsl:attribute>
          </xsl:if>
    

    and similar for the <a>.

    0 讨论(0)
提交回复
热议问题