Mike Maxwell wrote:
> We have an XML structure that we've added to DocBook (v5), which looks 
> like this in the RNC format:
>          element bundle {
>            langData+,
>            gloss
>          }
> So it has a variable number of daughters--at least two, sometimes three, 
> and at least theoretically more.
> 
> This structure itself is embedded inside another (invariant) structure; 
> the parent will always have at least one 'bundle', and is created using 
> an xxe <elementTemplate>.
> 
> We currently have two such templates: one contains a bundle with two 
> daughters--one langData and one gloss; the other contains a bundle with 
> three daughters--two langData elements, and of course one gloss element. 
> The <langData> and <gloss> elements each contain mixed text elements 
> (generally plain text, or text plus <emphasis> or <superscript>).
> 
> We want to assign an XXE macro (and a keystroke) to create additional 
> 'bundle' structures inside this parent, but with a constraint: the 
> additional bundles must have the same number of daughters as the 
> existing bundle.  That is, if the existing <bundle> has one <langData> 
> element, so must the new bundle; or if the existing one has two such 
> elements, so must the new one.  Furthermore, the new <langData> and 
> <gloss> elements should be empty, with no text inside.
> 
> I haven't found a way to do this.  I've tried various things, e.g.
>          <command name="selectNode"
>                   parameter="ancestorOrSelf[implicitElement]
>                   {http://casl.umd.edu/Interlinearization}bundle"/>
>          <command name="copy" parameter="[implicitElement]"/>
>          <command name="paste" parameter="after[implicitElement]"/>
> But this copies the text *with* the <langData> and <gloss> elements.  I 
> haven't found a way to automatically delete the text inside these.  I 
> thought maybe
>          <command name="replaceText" parameter="[ra] '.' ''"/>
> would work (thinking it would restrict the replacement to the selected 
> new node), but this appears to hang (possibly it's trying to replace all 
> the text in the entire document, one character at a time?).

Probably.



> 
> I've also tried
>          <command name="insertNode" parameter="sameElementAfter"/>
> but this appears to insert the minimal element allowed by the schema, in 
> this case a <bundle> with a single <langData> element (and a single 
> <gloss>), regardless of whether the existing <bundle> has one or two 
> <langData> elements.
> 
> I've tried a few variants of these, with no luck.
> 
> Is there a way to automatically construct a copy of an element, but 
> without any text it might contain? Maybe a copy to a certain depth?

Yes, your macro needs to invoke a *process* command (see
http://www.xmlmind.com/xmleditor/_distrib/doc/commands/process.html) that:

[1] Saves the selection to disk. See copyDocument
http://www.xmlmind.com/xmleditor/_distrib/doc/commands/copyDocument.html

[2] Transform it. See transform
http://www.xmlmind.com/xmleditor/_distrib/doc/commands/transform.html

[3] Returns the result of the transformation for use by paste. See read
http://www.xmlmind.com/xmleditor/_distrib/doc/commands/read.html

--> We strongly recommend to wait for a few days before attempting to do
that because we are about to release v4.7 which allows to embed a XSLT 1
or 2 stylesheet in a macro. This new facility is at the same time more
convenient to use and more efficient than invoke a process command from
within a macro.

Actual example: (look at <transform source="%_">)

---
<binding>
  <keyPressed code="F2" />
  <keyPressed code="RIGHT" />
  <command name="bookmap.demote" />
</binding>

<command name="bookmap.demote">
  <macro undoable="true" label="Demote">
    <sequence>
      <test context="$selectedElement"
            expression="(self::part and
                         name(preceding-sibling::*[1]) = 'part') or
                        (self::appendix and
                         name(preceding-sibling::*[1]) = 'appendix') or
                        ((self::chapter or
                          self::topicref or
                          self::topichead or
                          self::topicgroup) and
                         (name(preceding-sibling::*[1]) = 'chapter' or
                          name(preceding-sibling::*[1]) = 'topicref' or
                          name(preceding-sibling::*[1]) = 'topichead' or
                         name(preceding-sibling::*[1])='topicgroup'))"/>
      <set variable="container" context="$selectedElement"
           expression="preceding-sibling::*[1]" />
      <command name="cut" />

      <choice>
        <sequence>
          <test context="$container" expression="self::part" />
          <get expression="$clipboard" />

          <!-- The part root element becomes a chapter.
               The chapter children become topicrefs.
               Otherwise descendants are unchanged. -->
          <transform source="%_">
            <xsl:stylesheet version="1.0" xmlns=""
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

              <xsl:template match="/part">
                <chapter>
                  <xsl:apply-templates select="@*|node()"/>
                </chapter>
              </xsl:template>

              <xsl:template match="/part/chapter">
                <topicref>
                  <xsl:apply-templates select="@*|node()"/>
                </topicref>
              </xsl:template>

              <xsl:template match="@*|node()">
                <xsl:copy>
                  <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
              </xsl:template>

            </xsl:stylesheet>
          </transform>

          <set variable="clipboard"
               expression="%_" plainString="true" />
        </sequence>

        <sequence>
          <get expression="$clipboard" />

          <!-- The chapter or appendix root element becomes a topicref.
               Descendants are unchanged. -->
          <transform source="%_">
            <xsl:stylesheet version="1.0" xmlns=""
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

              <xsl:template match="/chapter|/appendix">
                <topicref>
                  <xsl:apply-templates select="@*|node()"/>
                </topicref>
              </xsl:template>

              <xsl:template match="@*|node()">
                <xsl:copy>
                  <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
              </xsl:template>

            </xsl:stylesheet>
          </transform>

          <set variable="clipboard"
               expression="%_" plainString="true" />
        </sequence>
      </choice>

      <choice>
        <sequence>
          <set variable="selectedElement"
               context="$container/*[last()]" expression="." />
          <command name="paste" parameter="after" />
        </sequence>

        <sequence>
          <set variable="selectedElement" expression="$container" />
          <command name="paste" parameter="into" />
        </sequence>
      </choice>

      <command name="center" />
    </sequence>
  </macro>
</command>
---



> 
> It is the case that all the <bundle>s in any given document will have 
> the same number of <langData> objects.  So I suppose I could create some 
> kind of empty <bundle> in each document, maybe inside a <remark> (so it 
> wouldn't appear) with an xml:id, and make the macro copy that using 
> selectById, then searching inside this <remark> for the daughter node to 
> be copied; then it would need to find its way back to where the 
> insertion is supposed to take place...

This wouldn't be very elegant. I *think* (not 100% sure, because what
you want to do is pretty advanced) that the new macro/transform facility
found in XXE v4.7 should allow you to implement that more elegantly.



---
PS: As usual, writing a command in Java is the most straightforward and
most efficient way to solve this kind of problem. But sometimes, one
(even us) is too lazy to write Java code, compile it, package it,
declare it, etc. Besides, advanced XXE macros are somewhat challenging,
and hence fun, to write.




 
--
XMLmind XML Editor Support List
[email protected]
http://www.xmlmind.com/mailman/listinfo/xmleditor-support

Reply via email to