0

I would like to add a node based on , but the problem is the categories are in a separate file and moreover I would like to loop to find all based on .

Let me show an example:

category.xml:

<ROOT>
<GROUPITEM>
<G_ID>1368</G_ID>
<GROUP>Phone</GROUP>
<PARENT>0</PARENT>
</GROUPITEM>

<GROUPITEM>
<G_ID>1194</G_ID>
<GROUP>Apple</GROUP>
<PARENT>1368</PARENT>
</GROUPITEM>

<GROUPITEM>
<G_ID>1195</G_ID>
<GROUP>2019</GROUP>
<PARENT>1194</PARENT>
</GROUPITEM>
</ROOT>

item.xml:

<ROOT>
<SHOPITEM>
    <PRODUCT_ID>96555</PRODUCT_ID>
    <GROUP_ID>1195</GROUP_ID>
    <PRODUCT_NAME>Apple iPhone 8 Plus</PRODUCT_NAME>
</SHOPITEM>
</ROOT>

Example output:

<ROOT>
<SHOPITEM>
    <PRODUCT_ID>96555</PRODUCT_ID>
    <GROUP_ID>1195</GROUP_ID>
    <PRODUCT_NAME>Apple iPhone 8 Plus</PRODUCT_NAME>
    <CATEGORY>Phone | Apple | 2019</CATEGORY>
</SHOPITEM>
</ROOT>

In simple words I am looking for a way to create node (in item.xml) and add here value ( from category.xml) based on (item.xml): search in category.xml for the same -> if found, add it -> search more based on (if success add separator + value) -> loop.

2
  • Does your processor support XSLT 2.0? Commented Dec 2, 2019 at 9:41
  • Yes, XSLT 2.0 or 3.0, doesn't matter. Commented Dec 2, 2019 at 9:46

1 Answer 1

1

Try something like (untested):

XSLT 2.0

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

<xsl:key name="group" match="GROUPITEM" use="G_ID" />

<xsl:template match="SHOPITEM">
    <xsl:copy>
        <xsl:copy-of select="*"/>
        <CATEGORY>
            <xsl:apply-templates select="key('group', GROUP_ID, document('category.xml'))"/>
        </CATEGORY>
    </xsl:copy>
</xsl:template>

<xsl:template match="GROUPITEM">
    <xsl:variable name="parent" select="key('group', PARENT)" />
    <xsl:if test="$parent">
        <xsl:apply-templates select="$parent"/>
        <xsl:text> | </xsl:text>
    </xsl:if>
    <xsl:value-of select="GROUP"/>
</xsl:template>

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

3 Comments

You are a genius, it seems so easy after reading someone else code.
How would you modify the code to leave <ROOT> node in the output? I tried <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template>, but it is duplicating the <CATEGORY>
I believe adding the identity transform template as you show should work. <CATEGORY> cannot be duplicated if it doesn't exist in the source XML.

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.