Get document line by line, excluding specific sections

I would like to be able to get document content from other pages, line by line, section by section. I am currently able to get the full document using the following code:

#set ($xwql = "where doc.space like 'my space%'")
#foreach ($item in $services.query.xwql($xwql).execute())
  ===**[[$item]]**===
  #set($document = $xwiki.getDocument($item))
  $document.getContent()

#end

By including/excluding specific sections, I’m looking to replicate the behavior of the “include page” macro which has a feature of only retrieving specific sections.

Any suggestions?

You can use $document.xdom and then traverse the XDOM tree to get what you want. See https://rendering.xwiki.org/xwiki/bin/view/Main/WebHome and https://rendering.xwiki.org/xwiki/bin/view/Main/GettingStarted#HExamples

Thanks. That worked out for me

Actually it’s $document.getXDOM()

So I can get document content line by line just fine with the following code:

#foreach ($block in $document2.getXDOM().getBlocks('class:ParagraphBlock', 'DESCENDANT'))
  #set ($xwikiSyntax = $services.rendering.render($block, "xwiki/2.1"))
  $xwikiSyntax
#end

I’m having trouble figuring out how to get the text under headers though, line by line. I can get headers with the following code:

  #set($document = $xwiki.getDocument($item))
    ===**[[$item]]**===
    ##$document.getContent()
    #foreach ($block in $document.getXDOM().getBlocks('class:HeaderBlock', 'DESCENDANT'))
      #set ($xwikiSyntax = $services.rendering.render($block, "xwiki/2.1"))
      $xwikiSyntax
      #if ($block.id == "HHeading1")
        <render lines here>
      #end   
    #end
  #end

I am unsure of what to do at “render lines here”. I need some kind of XDOM getter function that takes as a parameter a header, but I have yet to find one.

Thanks.

You need to find the SectionBlock instead of the HeaderBlock (the Header Block only contains the heading, as children). The children of the SectionBlock contains the content of the section.

Ok, I got it to work where I can pull entire sections based on header. Here is my code

#set ($items = $services.query.xwql($xwql).execute())
#foreach ($item in $items)

  #set($document = $xwiki.getDocument($item))
  ===**[[$item]]**===
  #foreach ($block in $document.getXDOM().getBlocks('class:SectionBlock', 'DESCENDANT'))
    #set ($t = $block.getChildren().get(0))
    #if($t.id == "HHeading1")
      $services.rendering.render($block, "xwiki/2.1")
    #end
  #end
#end```

The only issue now is I’d like to be able to read in each line of the section one at at a time. My previous method where I use getBlocks with class:ParagraphBlock won’t work though. I tried playing with the code and this is what I came up with:

#set( $xwql = "select doc from Document as doc where doc.parent like '%006 test.WebHome' order by doc.title")

#set ($items = $services.query.xwql($xwql).execute())

#foreach ($item in $items)
  #set($document = $xwiki.getDocument($item))
  ===**[[$item]]**===
  #foreach ($block in $document.getXDOM().getBlocks('class:SectionBlock', 'DESCENDANT'))
    #set ($xwikiSyntax = $services.rendering.render($block, "xwiki/2.1"))
    #set ($t = $block.getChildren())
    $t
  #end
#end

This will then output an array of all the headers and paragraph blocks i.e.

org.xwiki.rendering.block.HeaderBlock@4ca301ba, org.xwiki.rendering.block.ParagraphBlock@29c0c4c1, org.xwiki.rendering.block.ParagraphBlock@29c0c4c1…

However, when I try to call $services.rendering.render on $t, I get no output. If I could get the actual content from these elements, I would have what I need. If anyone knows how to do that, please let me know.

The render() API takes a Block as the first parameter but you’re passing it a List, so it cannot work. You should wrap the List in a CompositeBlock. However there’s no script API to do this from Velocity :wink:

In Groovy you’d write:

{{groovy}}
import org.xwiki.rendering.block.match.*
import org.xwiki.rendering.block.*
def mydoc = xwiki.getDocument('Sandbox.WebHome')
mydoc.getXDOM().getBlocks(new ClassBlockMatcher(SectionBlock.class), Block.Axes.DESCENDANT).each() {
  println services.rendering.render(new CompositeBlock(it.getChildren()), "xwiki/2.1")
}
println ""
{{/groovy}}

Notes:

  1. Note the last println which is needed for the output of the Groovy macro to not be considered as XDOM. See https://extensions.xwiki.org/xwiki/bin/view/Extension/Script%20Macro#HReturn Thus you could also write:
      {{groovy}}
      import org.xwiki.rendering.block.match.*
      import org.xwiki.rendering.block.*
      def mydoc = xwiki.getDocument('Sandbox.WebHome')
      mydoc.getXDOM().getBlocks(new ClassBlockMatcher(SectionBlock.class), Block.Axes.DESCENDANT).each() {
        println it.getChildren()
     }
     {{/groovy}}
    
  2. You’ll need Programming Rights