I have two XML file.
First XML
<annunci>
<annuncio>
<any_info>222</any_info>
<reference>333</reference>
.
.
<lot_of_info> </lot_of_info>
.
.
<some_info>1</some_info>
<images>
</images>
</annuncio>
Second XML
<images>
<img>
<url>http://example.com/xml/img/333/somefile</url>
<type>0</type>
<public>1</public>
<share>1</share>
</img>
<img>
<url>http://example.com/xml-feed/img/333/somefile</url>
<type>0</type>
<public>1</public>
<share>1</share>
</img>
</images>
Merging two XML using first file <reference> (example: 333) and <url> on second file with substring (folder) with same number (example: https://example.com/xml-feed/img/333/file1 and https://example.com/xml-feed/img/333/file2) to get a final XML like this one:
<annunci>
<annuncio>
<any_info>222</any_info>
<reference>333</reference>
.
.
<lot_of_info> </lot_of_info>
.
.
<some_info>1</some_info>
<images>
<img>
<url>http://example.com/xml/img/333/file1</url>
<type>0</type>
<public>1</public>
<share>1</share>
</img>
<img>
<url>http://example.com/xml-feed/img/333/file2</url>
<type>0</type>
<public>1</public>
<share>1</share>
</img>
</images>
</annuncio>
I try this but with no luck:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!-- identity template: copies all nodes and attributes as-is -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- template to add the <img> elements from the second XML file -->
<xsl:template match="/annunci/annuncio/images">
<xsl:copy>
<!-- add the <img> elements from the second XML file that have a matching <url> -->
<xsl:for-each select="document('second.xml')/images/img[contains(url, /annunci/annuncio/reference)]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Because I need to copy just ... with matching URL inside annuncio/annunci/images
CodePudding user response:
I would use a key <xsl:key name="ref" match="images/img" use="tokenize(url, '/')[last() - 1]"/>
and then e.g.
<xsl:template match="/annunci/annuncio/images">
<xsl:copy>
<xsl:copy-of select="key('ref', ../reference, doc('second.xml'))"/>
</xsl:copy>
</xsl:template>
CodePudding user response:
You could modify your second template to this :
<!-- template to add the <img> elements from the second XML file -->
<xsl:template match="images">
<xsl:variable name="ref" select="../reference"/>
<xsl:copy>
<!-- add the <img> elements from the second XML file that have a matching <url> -->
<xsl:for-each select="document('second.xml')/images/img[contains(url, $ref)]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
(Although as pointed out in the other answer, using a key for lookups is the best practice.)
To make sure that you don't match sub-patterns of your reference id in the URL you could do something like this :
<xsl:for-each select="document('second.xml')/images/img[contains(url, concat('/',$ref,'/'))]">