Selecting nodes from a data definition

voltmer1's Avatar

voltmer1

17 Jun, 2016 02:47 PM

I am learning Velocity and having a tough time understanding the methods used to select xml nodes, traversing and iterating over a group within fields created within a Data Definition. I am trying to display the value of "student-year" and "student-term" and iterate through the courses and credits within the group "student-term".

Here is my Data Definition:

<system-data-structure>
    <text identifier="program-name" label="Program Name" required="true"/>
    <text multi-line="true" identifier="program-description" label="Program Description" required="true"/>
    <group identifier="course-sequence" label="Course Sequence">
        <group identifier="student-year" label="Student Year" multiple="true" maximum-number="4">
            <text type="multi-selector" identifier="year" label="Year">
                <selector-item value="Freshman" selected="true"/>
                <selector-item value="Sophomore"/>
                <selector-item value="Junior"/>
                <selector-item value="Senior"/>
            </text>
            <group identifier="student-term" label="Student Term" multiple="true" maximum-number="3">
                <text type="multi-selector" identifier="term" label="Term">
                    <selector-item value="Fall" selected="true"/>
                    <selector-item value="Winter"/>
                    <selector-item value="Spring"/>
                </text>
                <text identifier="course-1" label="Course 1" required="true"/>
                <text identifier="course-1-credit" label="Course 1 Credit" required="true"/>
                <text identifier="course-2" label="Course 2" required="true"/>
                <text identifier="course-2-credit" label="Course 2 Credit" required="true"/>
                <text identifier="course-3" label="Course 3" required="true"/>
                <text identifier="course-3-credit" label="Course 3 Credit" required="true"/>
                <text identifier="course-4" label="Course 4" required="true"/>
                <text identifier="course-4-credit" label="Course 4 Credit" required="true"/>
                <text identifier="course-5" label="Course 5" required="true"/>
                <text identifier="course-5-credit" label="Course 5 Credit" required="true"/>
            </group>
        </group>
    </group>
</system-data-structure>

And here is my Velocity format:

#set ( $page = $_XPathTool.selectSingleNode($contentRoot, "/system-index-block/calling-page/system-page") ) #set ( $data = $page.getChild("system-data-structure") )

#set ( $progName = $data.getChild("program-name") ) #set ( $progDesc = $data.getChild("program-description") ) #set ( $courseSequ = $_XPathTool.selectNodes($data,"course-sequence") )

#set ( $year = $_XPathTool.selectSingleNode($data, "year/value") ) #set ( $term = $_XPathTool.selectSingleNode($data, "term/value") ) #set ( $course = $_XPathTool.selectNodes($data, "course[.!='']") )

#courseSequence ( $year, $term )

#macro ( courseSequence $yr $trm )

 <ul>
    #foreach ( $crs in $trm ) 
    #set ( $courseName = $crs.getChild("course-1") )
    <li>$courseName.value</li>
    #end
</ul>

#end

  1. 1 Posted by Wing Ming Chan on 17 Jun, 2016 03:23 PM

    Wing Ming Chan's Avatar

    Hi,

    Before I try to offer help, I want one thing clarified. About the data definition you provided, is it a data definition associated with a content type, or is it used by data definition blocks? it does not look like one for pages, because it is too simple. It does not look like one for data definition blocks, because in your Velocity code you dealt with calling-page. How should I understand your data definition?

    Wing

  2. 2 Posted by voltmer1 on 17 Jun, 2016 03:31 PM

    voltmer1's Avatar

    As it stands now, the data definition is not associated with a content type, but I didn't think it had to be when I am just trying to learn. It is tied to a calling page block on a section of a page template.

    Eventually, I would like the macro to iterate over each student-year group and display each student-term group with it's containing courses. Just trying to get anything to display now.

  3. 3 Posted by Wing Ming Chan on 17 Jun, 2016 03:35 PM

    Wing Ming Chan's Avatar

    I assume that by "on a section of a page template", you mean that the block is attached to a region at the page level. Correct me if I am wrong.

    What do you mean by "It is tied to a calling page block"? Since the calling-page block is an index block, how do you tie a data definition with an index block?

    There reason why I ask these questions: I want to duplicate your setup so that I can write the Velocity format.

    Wing

  4. 4 Posted by voltmer1 on 17 Jun, 2016 03:41 PM

    voltmer1's Avatar

    I am not tying the data definition itself to the calling page block. I meant to say that I had a content region with a calling block and my Velocity format on a page template that uses the Data Definition. Does that make sense?

  5. 5 Posted by Wing Ming Chan on 17 Jun, 2016 03:51 PM

    Wing Ming Chan's Avatar

    Let me try this. Go to Cascade. Look at the data definition, and click the Relationships tab on the top. What do you see?

    One more thing. On my site, you can find Velocity Tutorial. You might want to try that, though the tutorial goes very deep into Velocity.

    Wing

  6. 6 Posted by voltmer1 on 17 Jun, 2016 03:59 PM

    voltmer1's Avatar

    It shows my content type of "Programs of Study". This has the data definition that the page template is based off of. Am I doing something wrong? There are so many parts to remember.

  7. 7 Posted by Wing Ming Chan on 17 Jun, 2016 04:47 PM

    Wing Ming Chan's Avatar

    OK, try the following:

    #set ( $page = $_XPathTool.selectSingleNode( $contentRoot, "calling-page/system-page" ) ) 
    #set ( $data = $page.getChild( "system-data-structure" ) )
    #set( $progName = $data.getChild( "program-name" ).value )
    Program name: $progName<br />
    #set( $progDesc = $data.getChild( "program-description" ).value )
    Program Description: $progDesc<br />
    #set( $courseSequ = $data.getChild( "course-sequence" ) )
    #set( $year = $_XPathTool.selectSingleNode( $courseSequ, "student-year/year/value" ).value )
    Year: $year<br />
    #set( $studTerm = $courseSequ.getChild( "student-year" ).getChild( "student-term" ) )
    #set( $term = $studTerm.getChild( "term" ).getChild( "value" ).value )
    Term: $term<br />
    #courseSequence( $year $studTerm ) ## not $term!!!
    #macro( courseSequence $yr $trm )
    <ul>
        #foreach( $num in [1..5] )
            #set( $courseName = $trm.getChild( "course-${num}" ).value )
            #set( $courseCredit = $trm.getChild( "course-${num}-credit" ).value )
            <li>$courseName: $courseCredit</li>
        #end
    </ul>
    #end
    

    Wing

  8. 8 Posted by voltmer1 on 17 Jun, 2016 06:36 PM

    voltmer1's Avatar

    Perfect Wing!
    I didn't think about using an array in the foreach either. Is that syntax something specific to VTL? I hadn't seen it in Java or C#.

  9. 9 Posted by Wing Ming Chan on 17 Jun, 2016 06:48 PM

    Wing Ming Chan's Avatar

    [1..5] is a java.util.ArrayList<E> object. The syntax of #foreach is similar to Java's counterpart for( int num : nums ).

    Wing

  10. 10 Posted by voltmer1 on 17 Jun, 2016 07:37 PM

    voltmer1's Avatar

    Thanks Wing!

    I've tried to add the functionality to list all the additional terms in the year, but I am not quite getting it. It is pulling only the first term and repeating it for the number of actual "student-term" groups I have entered on my page.

    #set ( $page = $_XPathTool.selectSingleNode( $contentRoot, "calling-page/system-page" ) ) 
    #set ( $data = $page.getChild( "system-data-structure" ) )
    #set( $progName = $data.getChild( "program-name" ).value )
    <h2>$progName Course Sequence</h2>
    
    #set( $seqGroup = $_XPathTool.selectNodes($data, "course-sequence/student-year") )
    #set( $courseSequ = $data.getChild( "course-sequence" ) )
    #set( $year = $_XPathTool.selectSingleNode( $courseSequ, "student-year/year/value" ).value )
    
    #set( $studTerm = $courseSequ.getChild( "student-year" ).getChild( "student-term" ) )
    #set( $terms = $_XPathTool.selectNodes($seqGroup, "student-term") )
    #set( $term = $studTerm.getChild( "term" ).getChild( "value" ).value )
    Year: $year<br />
    
    #foreach( $num in $terms)
    Term: $term<br />
        <div>#courseSequence( $year $studTerm )</div>
    #end
    
    #macro( courseSequence $yr $trm )
    <ul>
        #foreach( $num in [1..5] )
            #set( $courseName = $trm.getChild( "course-${num}" ).value )
            #set( $courseCredit = $trm.getChild( "course-${num}-credit" ).value )
         <li>$courseName: $courseCredit</li>
        #end
    </ul>
    #end
    
  11. 11 Posted by Wing Ming Chan on 17 Jun, 2016 08:04 PM

    Wing Ming Chan's Avatar

    You are not looping through the correct object:

    #set( $page = $_XPathTool.selectSingleNode( $contentRoot, "calling-page/system-page" ) ) 
    #set( $data = $page.getChild( "system-data-structure" ) )
    #set( $progName = $data.getChild( "program-name" ).value )
    <h2>$progName Course Sequence</h2>
    #set( $seqence = $data.getChild( "course-sequence" ) )
    #set( $studentYears = $seqence.getChildren( "student-year" ) )
    #if( $studentYears.size() > 0 )
        #foreach( $studentYear in $studentYears )
            #set( $year     = $_XPathTool.selectSingleNode( $studentYear, "year/value" ).value )
            #set( $studTerm = $studentYear.getChild( "student-term" ) )
            #set( $term     = $_XPathTool.selectSingleNode( $studTerm, "term/value" ).value )
            Year: $year<br />
            Term: $term<br />
            <div>#courseSequence( $year $studTerm )</div>
        #end
    #end
    #macro( courseSequence $yr $trm )
    <ul>
        #foreach( $num in [1..5] )
            #set( $courseName = $trm.getChild( "course-${num}" ).value )
            #set( $courseCredit = $trm.getChild( "course-${num}-credit" ).value )
         <li>$courseName: $courseCredit</li>
        #end
    </ul>
    #end
    

    Wing

  12. 12 Posted by voltmer1 on 17 Jun, 2016 08:40 PM

    voltmer1's Avatar

    For some reason, this only pulls the first term of each year.

  13. 13 Posted by Wing Ming Chan on 17 Jun, 2016 09:03 PM

    Wing Ming Chan's Avatar

    I forgot that student-term is also a multiple field. Then when you retrieve the elements, use getChildren( "student-term" ) instead. Of course you need to loop through the elements you retrieve. Can I leave this to you?

    Wing

  14. 14 Posted by voltmer1 on 20 Jun, 2016 02:05 PM

    voltmer1's Avatar

    Wing, I've tried, but I can't seem to get more than 2 terms to display for some reason. Currently it only iterates through the years, of which I have created 2. So you are right, It needs to iterate through the "student-terms" as well, I just can't get it to happen.

  15. 15 Posted by Wing Ming Chan on 20 Jun, 2016 02:16 PM

    Wing Ming Chan's Avatar

    Try this:

    #set( $page = $_XPathTool.selectSingleNode( $contentRoot, "calling-page/system-page" ) ) 
    #set( $data = $page.getChild( "system-data-structure" ) )
    #set( $progName = $data.getChild( "program-name" ).value )
    <h2>$progName Course Sequence</h2>
    ## there is only one course-sequence element
    #set( $seqence = $data.getChild( "course-sequence" ) )
    ## the course-sequence element can have multiple student-year elements
    #set( $studentYears = $seqence.getChildren( "student-year" ) )
    #foreach( $studentYear in $studentYears )
        #set( $year      = $_XPathTool.selectSingleNode( $studentYear, "year/value" ).value )
        #set( $studTerms = $studentYear.getChildren( "student-term" ) )
        
        Year: $year<br />
            
        #foreach( $studTerm in $studTerms )
            #set( $term      = $_XPathTool.selectSingleNode( $studTerm, "term/value" ).value )
            Term: $term<br />
            <div>#courseSequence( $year $studTerm )</div>
        #end
    #end
    #macro( courseSequence $yr $trm )
    <ul>
        #foreach( $num in [1..5] )
            #set( $courseName = $trm.getChild( "course-${num}" ).value )
            #set( $courseCredit = $trm.getChild( "course-${num}-credit" ).value )
         <li>$courseName: $courseCredit</li>
        #end
    </ul>
    #end
    

    I removed the size test because a multiple field must have at least one instance.

    Wing

  16. 16 Posted by voltmer1 on 20 Jun, 2016 02:32 PM

    voltmer1's Avatar

    Thanks for all your help Wing! It's working correctly now!

    I believe I will have to practice writing a few more of these.

  17. Bradley Wagner closed this discussion on 20 Jun, 2016 03:15 PM.

  18. voltmer1 re-opened this discussion on 20 Jun, 2016 08:52 PM

  19. 17 Posted by voltmer1 on 20 Jun, 2016 08:52 PM

    voltmer1's Avatar

    I decided that my field "program-description" needed to be a WYSIWYG, but none of the formatting is working when it's pulled in. Do I need to change something in my format?

    #set ( $page = $_XPathTool.selectSingleNode($contentRoot, "/system-index-block/calling-page/system-page") )
    #set ( $data = $page.getChild("system-data-structure") )
    
    #set ( $progName = $data.getChild("program-name") )
    #set ( $progDesc = $data.getChild("program-description") )
    
    <h2>$_EscapeTool.xml($progName.value)</h2>
    <p>$_EscapeTool.xml($progDesc.value)</p>
    
  20. 18 Posted by Ryan Griffith on 22 Jun, 2016 12:53 PM

    Ryan Griffith's Avatar

    Hi,

    I noticed your latest comment is a duplicate of this discussion you opened up recently. To help avoid confusion, I am going to go ahead and close this one out in favor of the other.

    I'm going to go ahead and close this discussion, please feel free to comment or reply to re-open if you have any additional questions about your initial problem.

    Have a great day!

  21. Ryan Griffith closed this discussion on 22 Jun, 2016 12:53 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac