Create new node based on search from existing node

I am looking for a way to create a new node from existing node and remove the searched string from existing node.

Example:

<RSS>
<ITEM>
      <PRODUCT_ID>86258</PRODUCT_ID>
      <EAN>8595174240939</EAN>
      <PRODUCT_NAME>Apple T-Shirt, 16"</PRODUCT_NAME>
</ITEM>
<ITEM>
      <PRODUCT_ID>86255</PRODUCT_ID>
      <EAN>8595174240931</EAN>
      <PRODUCT_NAME>Orange T-Shirt, 18"</PRODUCT_NAME>
</ITEM>
</RSS>

I would like to search for 16", 18" in the example above, I think regex \d+"$ (number + " + end of string) would do the trick. In the next step I would like to cut this searched string with the comma (,.*\d+"$)

Output.xml:

<RSS>
<ITEM>
      <PRODUCT_ID>86258</PRODUCT_ID>
      <EAN>8595174240939</EAN>
      <PRODUCT_NAME>Apple T-Shirt</PRODUCT_NAME>
      <SIZE>16"</SIZE>
</ITEM>
<ITEM>
      <PRODUCT_ID>86255</PRODUCT_ID>
      <EAN>8595174240931</EAN>
      <PRODUCT_NAME>Orange T-Shirt</PRODUCT_NAME>
      <SIZE>18"</SIZE>
</ITEM>
</RSS>

Upvotes: 0

Views: 32

Answers (2)

zx485
zx485

Reputation: 29022

To apply this change using RegEx'es, you have to use XSLT-2.0, like this:

<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"/>

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

  <xsl:template match="PRODUCT_NAME">
    <xsl:analyze-string select="." regex='(.*?),?\s?(\d{{2}}")$'>
      <xsl:matching-substring>
        <PRODUCT_NAME><xsl:value-of select="regex-group(1)" /></PRODUCT_NAME>
        <SIZE><xsl:value-of select="regex-group(2)" /></SIZE>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
        <PRODUCT_NAME><xsl:copy-of select="." /></PRODUCT_NAME>
      </xsl:non-matching-substring>
    </xsl:analyze-string>
  </xsl:template>

</xsl:stylesheet>

Its output is:

<?xml version="1.0" encoding="UTF-8"?>
<RSS>
   <ITEM>
      <PRODUCT_ID>86258</PRODUCT_ID>
      <EAN>8595174240939</EAN>
      <PRODUCT_NAME>Apple T-Shirt</PRODUCT_NAME>
      <SIZE>16"</SIZE>
   </ITEM>
   <ITEM>
      <PRODUCT_ID>86255</PRODUCT_ID>
      <EAN>8595174240931</EAN>
      <PRODUCT_NAME>Orange T-Shirt</PRODUCT_NAME>
      <SIZE>18"</SIZE>
   </ITEM>
</RSS>

Upvotes: 2

Sebastien
Sebastien

Reputation: 2714

This would give you the desired output:

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

  <xsl:output method="xml" indent="yes"/>

    <xsl:template match="ITEM">
        <xsl:copy>
            <xsl:apply-templates/>
            <xsl:if test="contains(PRODUCT_NAME,'T-Shirt')">
                <SIZE><xsl:value-of select="substring-after(PRODUCT_NAME,', ')"/></SIZE>
            </xsl:if>
       </xsl:copy>
    </xsl:template>

    <xsl:template match="PRODUCT_NAME[contains(.,'T-Shirt')]">
        <PRODUCT_NAME><xsl:value-of select="substring-before(.,',')"/></PRODUCT_NAME>
    </xsl:template>

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

</xsl:stylesheet>

You can try it here: https://xsltfiddle.liberty-development.net/bFWR5Eo

Upvotes: 0

Related Questions