xsl-list
[Top] [All Lists]

Re: [xsl] A use-case for xsl:merge?

2019-02-15 14:21:12
On 15.02.2019 21:01, John Dziurlaj john(_at_)hiltonroscoe(_dot_)com wrote:
The element prototypes can be in the same document or different documents,
but for the purposes of the XSLT3 we are only concerned with merging the
external references, such that we have a fully dereferenced (i.e.
standalone) XML instance.

I already have code to pull in the external references (prototypes) and run
the XPath (via evaluate) on them. I've put all the code on GitHub to
hopefully make this easier to understand.

I am not sure I understand all that sample code, there are two XML documents, one seems incomplete.

I am not sure it is a use case for xsl:merge (order their matters and I am not sure about the order of your items to be merged), I think it can be done with recursive templates using `for-each-group`:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:xs="http://www.w3.org/2001/XMLSchema";
    xmlns:math="http://www.w3.org/2005/xpath-functions/math";
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:param name="prot-doc-uri" as="xs:string">prototype.xml</xsl:param>

    <xsl:param name="prot-doc" select="doc($prot-doc-uri)"/>

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:output indent="yes"/>

    <xsl:template match="*[@usehref]">
        <xsl:copy>
            <xsl:variable name="prototype" as="element()?">
                <xsl:evaluate xpath="@usehref" context-item="$prot-doc"/>
            </xsl:variable>
            <xsl:apply-templates select="." mode="merge-attributes">
                <xsl:with-param name="prototype" select="$prototype"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="." mode="merge-children">
                <xsl:with-param name="prototype" select="$prototype"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*" mode="merge-attributes">
        <xsl:param name="prototype"/>
<xsl:for-each-group select="@* except @usehref, $prototype/(@* except @name)" group-by="node-name()">
            <xsl:sequence select="."/>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="*" mode="merge-children">
        <xsl:param name="prototype"/>
<xsl:for-each-group select="*, $prototype/*" group-by="node-name()">
            <xsl:copy>
                <xsl:apply-templates select="." mode="merge-attributes">
<xsl:with-param name="prototype" select="current-group()[2]"/>
                </xsl:apply-templates>
                <xsl:apply-templates select="." mode="merge-children">
<xsl:with-param name="prototype" select="current-group()[2]"/>
                </xsl:apply-templates>
            </xsl:copy>
        </xsl:for-each-group>
    </xsl:template>

</xsl:stylesheet>


That assumes the first input is e.g. (note that I had to adjust the XPath expression to use "@name" instead of "name")

<root>
    <draw name="Text1" usehref="/proto/draw[@name = 'TextStyle1']">

        <ui>

            <textEdit/>

        </ui>

        <value>

            <text>This is some text</text>

        </value>

        <border/>

        <font weight="bold"/>

    </draw>
</root>


and the referenced file has e.g.

<proto>
    <draw name="TextStyle1" w="29.2864mm" h="5.2331mm">

        <ui>

            <textEdit/>

        </ui>

        <border>

            <edge presence="hidden"/>

        </border>

        <font size="12pt" typeface="Myriad Pro"/>

<margin topInset="0.5mm" bottomInset="0.5mm" leftInset="0.5mm" rightInset="0.5mm"/>

    </draw>
</proto>

then the result is

<root>
    <draw name="Text1" w="29.2864mm" h="5.2331mm">
      <ui>
         <textEdit/>
      </ui>
      <value>
         <text/>
      </value>
      <border>
         <edge presence="hidden"/>
      </border>
      <font weight="bold" size="12pt" typeface="Myriad Pro"/>
      <margin topInset="0.5mm"
              bottomInset="0.5mm"
              leftInset="0.5mm"
              rightInset="0.5mm"/>
   </draw>
</root>
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>