0

I have two inputs for transformation.

One is source XML source.xml and looks like this:

<ROOT>
    <row>
        <id>1</id>
        <value>FooBar</value>
    </row>
    <row>
        <id>2</id>
        <value>Bar</value>
    </row>
    <row>
        <id>3</id>
        <value>FooFoo</value>
    </row>
</ROOT>

Other one is supplied through parameter (<xsl:param name="input" />) into transformation. Structure is same as a XML above. But contains different number of rows and different values.

<ROOT>
    <row>
        <id>1</id>
        <value>Foo</value>
    </row>
    <row>
        <id>2</id>
        <value>Bar</value>
    </row>
</ROOT>

Now I need to merge those inputs. I want to iterate over source.xml and for each row's id decide if there is same id in variable and update. If there is not same id in variable $input I want to create new row. In other words: source.xml represents new data while input parameter represents data I already have. And I want them to merge. I think you get it.

I tried many ways to solve this, but I always stucked on comparing ids with creating unnecessary rows. The restrictions are those:

  • XSLT 1.0 limitation.
  • input for comparison can be imported only by using XSLT parameter.

Output should look like this:

<ROOT>
    <row>
        <id>1</id>
        <value>FooBar</value>
    </row>
    <row>
        <id>2</id>
        <value>Bar</value>
    </row>
    <row>
        <id>3</id>
        <value>FooFoo</value>
    </row>
</ROOT>
4
  • Well what type does your parameter have? A node set, a result tree fragment, a string with XML markup? Only showing <xsl:param name="input" /> does not tell us what kind of type your parameter will have. Commented Nov 19, 2015 at 17:44
  • Well, that is hard to tell because parameter is supplied automatically from engine and I have no control over it. I supposed it is node set or string with XML markup. I know I can invoke templates over it and run XPath expressions. I hope it helps Commented Nov 19, 2015 at 17:51
  • If you can use XPath then it is a node set. Why does the output have <row> <id>1</id> <value>Updated</value> </row> and not <row> <id>1</id> <value>Foo</value> </row> if the source.xml represents the new data? Commented Nov 19, 2015 at 17:55
  • I messed it up. Now it should be ok. Thanks for noticing Commented Nov 19, 2015 at 18:08

1 Answer 1

1

If the supplied parameter is indeed a node-set, then you could do:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="input" />

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

<xsl:template match="/ROOT">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:apply-templates select="$input/ROOT/row[not(id = current()/row/id)]"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.