开发者

orbeon: applying xslt transform in xbl on bound document

开发者 https://www.devze.com 2023-03-24 05:02 出处:网络
In Orbeon Forms I need to create a component (using XBL) that when bound to an instance like <OCinstructionitem>

In Orbeon Forms I need to create a component (using XBL) that when bound to an instance like

<OCinstructionitem>
  <OCp>paragraph 1</OCp>
  <OCp>paragraph 2 <OCem>with italics part</OCem> rest of paragraph 2 </OCp>
</OCinstructionitem>

creates an editable div like this:

<div contentEditable="true">
  <p>paragraph 1</p>
  <p>paragraph 2 <i>with italics part</i> rest of paragraph 2 </p>
</div>

My thought was that I need to do this using XSLT. I get this working when the to-be-transformed XML is inside the xforms document:

<oc:instructionitem>
   <OCinstructionitem>
      <!-- here the xml of above -->
      ...
   </OCinstructionitem>
</oc:instructionitem> 

but I want to let the XSLT operate on the bound node as in:

<oc:instructionitem ref="OCinstructionitem"/>

However, I canot access the bound node from the XSLT.

My question: is that just not possible? Or do I have to modify my XBL?

My XBL code:

<xbl:binding id="oc-instructionitem" element="oc|instructionitem">
    <xbl:template xxbl:transform="oxf:xslt">
        <xsl:transform version="2.0">
              <xsl:template match="@*|node()" priority="-100">
                   <xsl:apply-templates select="@*|node()"/>
              </xsl:template>
              <xsl:template match="text()" priority="-100" mode="in-paragraph">
                  <xsl:copy>
                     <xsl:value-of select="."/>
                  </xsl:copy>
              </xsl:template>
              <xsl:template match="OCem" mode="in-paragraph">
                  <x:i><xsl:value-of select="."/></x:i>
              </xsl:template>
              <xsl:template match="OCp">
                  <x:div>
                      <xsl:apply-templates mode="in-paragraph"/>
                  </x:div>
              </xsl:template>
              <xsl:template match="/*">
                <x:div contentEditable="true">
                    <xsl:apply-templat开发者_运维问答es/>
                </x:div>
            </xsl:template>
    </xsl:transform>
    </xbl:template>
</xbl:binding>

</xbl:xbl>

Any help would be greatly appreciated,

edit: after helpfull comment of tohuwawohu (below) It seems that you need to define a variable which is bound to the instance data. Like this:

<xsl:template match="oc:instructionitem">
   <xforms:group xbl:attr="model context ref bind" xxbl:scope="outer">
      <xxforms:variable name="binding" as="node()?" xxbl:scope="inner" >
         <xxforms:sequence select="." xxbl:scope="outer"/>
      </xxforms:variable>
      <xforms:group xxbl:scope="inner">
         <!-- Variable pointing to external single-node binding -->
         <xforms:group ref="$binding">
              <xsl:call-template name="main"/>
         </xforms:group>
      </xforms:group>
   </xforms:group>
</xsl:template>
<xsl:template name="main">
    <x:div contentEditable="true">
       <xforms:repeat nodeset="*">
           <xsl:call-template name="paragraph"/>
       </xforms:repeat>
    </x:div>
</xsl:template>

However, the XSLT elements still cannot act on the data. It can only generate XFORMS elements, which can act on the data. This means that something like <xsl:template match="OCp"> will never be selected. This is why the above code uses named templates. So the question still stands: can the bound data be made available to the xslt code?

Martijn


I didn't test it, but i think it should be possible by breaking the encapsulation. Without this, your XBL will only have access to the content of the bound node, as in your third code snippet. If you want to make the XBL access the XForms instance data, you will have to declare a variable inside the XBL that's pointing to the single-node binding of the bound node.

Here's the code snippet from the Wiki example:

<xforms:group xbl:attr="model context ref bind" xxbl:scope="outer">
    <xforms:group xxbl:scope="inner">
        <!-- Variable pointing to external single-node binding -->
        <xxforms:variable name="binding" as="node()?">
            <xxforms:sequence select="." xxbl:scope="outer"/>
        </xxforms:variable>
        ...
    </xforms:group>
</xforms:group>

Having defined the single-node binding like this, it should be possible to reference that variable and use it for xslt transformation. Just replace the XSLT template element matching the root node and point it to the content of the variable $binding:

<xsl:transform version="2.0">
    <xsl:template match="@*|node()" priority="-100">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:template>
    <xsl:template match="text()" priority="-100" mode="in-paragraph">
        <xsl:copy>
            <xsl:value-of select="."/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="OCem" mode="in-paragraph">
        <x:i><xsl:value-of select="."/></x:i>
    </xsl:template>
    <xsl:template match="OCp">
        <x:div>
            <xsl:apply-templates mode="in-paragraph"/>
        </x:div>
    </xsl:template>
    <xsl:template match="oc:instructionitem">
        <xforms:group ref="$binding">
          <x:div contentEditable="true">
              <xsl:apply-templates/>
          </x:div>
        </xforms:group>
    </xsl:template>

Hope this works for you. Maybe this requires making provisions if the bound node (in your example: oc:instructionitem) isn't empty, so the xslt may process both that content as well as the content of the $binding variable.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号