1

need help on how can I have all brand(?) in one line for each brands under the same record id?

input xml

<?xml version='1.0' encoding='UTF-8'?>
<ns1:Bags xmlns:ns1="test" id="3430">
  <ns1:inventory>
    <ns1:record id="3431" name="001">
      <ns1:brands>
        <ns1:brand brand1="kate spade" />
        <ns1:brand brand2="michael kors" />
        <ns1:brand brand3="coach" />
        <ns1:brand brand4="tory burch" />
        <ns1:brand brand5="dkny" />
      </ns1:brands>
    </ns1:record>
    <ns1:record id="3431" name="001">
      <ns1:brands>
        <ns1:brand brand1="calvin klein" />
        <ns1:brand brand2="fossil" />
        <ns1:brand brand3="tommy hilfiger" />
      </ns1:brands>
    </ns1:record>
    <ns1:record id="3435" name="002">
      <ns1:brands>
        <ns1:brand brand1="charles and keith" />
        <ns1:brand brand2="farfois" />
        <ns1:brand brand3="victoria's secret" />
      </ns1:brands>
    </ns1:record>
  </ns1:inventory>
</ns1:Bags>

output xml

<?xml version='1.0' encoding='UTF-8'?>
<ns1:Bags xmlns:ns1="test" id="3430">
  <ns1:inventory>
    <ns1:record id="3431" name="001">
      <ns1:brands>
        <ns1:brand brand1="kate spade" brand2="michael kors" brand3="coach" brand4="tory burch" brand5="dkny" />
        <ns1:brand brand1="calvin klein" brand2="fossil" brand3="tommy hilfiger" />
      </ns1:brands>
    </ns1:record>
    <ns1:record id="3435" name="002">
      <ns1:brands>
        <ns1:brand brand1="charles & keith" brand2="farfois" brand3="victoria's secret" />
      </ns1:brands>
    </ns1:record>
  </ns1:inventory>
</ns1:Bags>

tried to use grouping as advised but nothing happens and still not grouping the "record" by the same id. same with brand.

<xsl:template match="record">
    <xsl:for-each-group select="record" group-by="@id">
        <record id="{current-grouping-key()}">
        </record>
    </xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>

also tried below for "brand" but no success

<xsl:template match="brand">
    <xsl:element name="{concat('brand1', @brand2, @brand3, @brand4, @brand5)}">
    </xsl:element>
</xsl:template>
emma.a
  • 13
  • 5
  • Your templates do not match anything in your input, because it does not have an element named `record` or `brand`. – michael.hor257k Aug 13 '21 at 05:09
  • `xmlns:ns1=""` is not legal in XML 1.0. It's legal in XML 1.1, but your XML declaration specifies 1.0. You seem to be assuming you can ignore namespaces as irrelevant, but you can't: they're critical. – Michael Kay Aug 13 '21 at 07:40
  • michael.hor257k i realized I should add the prefix "ns1:" in my template.... Michael Kay you are right, i am assuming it can be ignored. i'm too ignorant in xslt and still learning i tried declaring the prefix namespace in my xslt but still showing the same result.. https://xsltfiddle.liberty-development.net/pNEj9dL – emma.a Aug 15 '21 at 15:51

1 Answers1

0

Perhaps like this:

  <xsl:template match="inventory">
    <xsl:copy>
      <xsl:for-each-group select="record" group-by="@id">
        <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <ns1:brands>
            <xsl:apply-templates select="current-group()/brands"/>
          </ns1:brands>
        </xsl:copy>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="brands">
    <brand>
      <xsl:apply-templates select="brand/@*"/>
    </brand>
  </xsl:template>
  

Assumes identity copy with e.g. <xsl:mode on-no-match="shallow-copy"/> is in place.

As for the namespaces you have added in the edit, see https://xsltfiddle.liberty-development.net/asoTKt/1 which declare xpath-default-namespace to allow for easy selection and also creates the result elements in the ns1 namespace:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
xpath-default-namespace="test"
xmlns:ns1="test"
version="3.0">
    
    <xsl:output indent="yes"/>

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

    <xsl:template match="inventory">
        <xsl:copy>
            <xsl:for-each-group select="record" group-by="@name">
                <xsl:copy>
                    <xsl:apply-templates select="@*"/>
                    <ns1:brands>
                        <xsl:apply-templates select="current-group()/brands"/>
                    </ns1:brands>
                </xsl:copy>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="brands">
        <ns1:brand>
            <xsl:apply-templates select="brand/@*" />
        </ns1:brand>
    </xsl:template>

</xsl:stylesheet>
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • thank you. I tried the one you suggested and it is working if there is no prefix "ns1:" https://xsltfiddle.liberty-development.net/asoTKt I added a declaration at the top for the ns1 format (xmlns:ns1="http://www.w3.org/1999/XSL/Format") and added ns1: when calling each element but still showing the same result https://xsltfiddle.liberty-development.net/pNEj9dL – emma.a Aug 15 '21 at 15:46
  • @emma.a, see the edit, I can only get namespace right if you show them in your samples. – Martin Honnen Aug 15 '21 at 15:55
  • i see... so i also need to add xpath-default-namespace aside from just declaring xmlns:ns1. will test this by adding the namespace and update you. i don't know if there is an impact but i was also using "exclude-result-prefixes="#all" on my previous attempt – emma.a Aug 15 '21 at 16:12
  • @emma.a, there are various ways to deal with namespaces, as long as there is a single namespace in the input document I think using `xpath-default-namespace` in XSLT 2 or 3 is the most convenient way to deal with that. For the output it is still not quite clear what you want as your question for the result continues to show `xmlns:ns1=""`. – Martin Honnen Aug 16 '21 at 09:19
  • It did work on my end...will take note of this. I still have a lot to learn but thank you for helping me out on this...as for the output.. apologies for the confusion, I updated the question above to "xmlns:ns1="test" – emma.a Aug 20 '21 at 13:46