Jamie Brace
Jamie Brace

Reputation: 185

Transforming child elements to attributes of the parent

I would like to transform the JOB_NUMBER field and the ORDERPK field to an Attribute of the "order" node, please can someone show me how?

I have the following XML;

<?xml version="1.0" encoding="UTF-8"?>
<dataroot
    xmlns:od="urn:schemas-microsoft-com:officedata" generated="2014-12-15T14:45:35">
    <order>
        <ORDERPK>2</ORDERPK>
        <JOB_x0020_NUMBER>S019191-9</JOB_x0020_NUMBER>
        <job_description>TESTDATA</job_description>
        <order_qty>1900</order_qty>
        <finishing_style>PB</finishing_style>
        <depth>10</depth>
        <width>8</width>
        <cover_pagination>4</cover_pagination>
        <text_pagination>12</text_pagination>
        <delivery_commence_date>15/12/2014</delivery_commence_date>
        <delivery_complete_date>15/12/2014</delivery_complete_date>
        <job_site>DG</job_site>
        <managing_printer>DG</managing_printer>
        <is_managing_printer>TRUE</is_managing_printer>
        <cust_order_ref>776031</cust_order_ref>
        <cust_code>Test</cust_code>
        <site_cce_name>Jamie</site_cce_name>
        <site_cce_email>[email protected]</site_cce_email>
        <sales_person_name>Jamie Brace</sales_person_name>
        <sales_person_email>[email protected]</sales_person_email>
    </order>
</dataroot>

This is what I'd like my data to look like;

<order JOB_NUMBER="S019191-9" ORDERPK="2">
<job_description>TESTDATA</job_description>
etc.

This the XSLT I have come up with so far, but in all honesty I'm not familiar with XML or XSLT at all.

<?xml version="1.0" encoding="UTF‐8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="xml" />
  <xsl:template match="/order">
    <root>
      <xsl:apply-templates select="order" />
    </root>
  </xsl:template>

  <xsl:template match="order">
    <order JOB_x0020_NUMBER="{@JOB_x0020_NUMBER}">
      <xsl:value-of select="order" />
    </order>
  </xsl:template>
</xsl:stylesheet>

Upvotes: 4

Views: 55

Answers (1)

Mathias M&#252;ller
Mathias M&#252;ller

Reputation: 22647

You were not far off. Start with an identity template that just copies everything to the output tree. Then, add more specific templates for all the exceptions you'd like to define to this basic, indiscriminate copying process.

The first template matches order and outputs a new order element with two new attributes. Their values are retrieved with attribute value templates. But then, the two elements that are now represented as attributes should not appear in the output. Therefore, a second template matches them and simply does nothing.

It is not clear from your question whether you'd like to leave all the rest of the child elements of order intact, but I assume it is what you want.

Stylesheet

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

<xsl:strip-space elements="*"/>

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

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

<xsl:template match="order">
    <order JOB_NUMBER="{JOB_x0020_NUMBER}" ORDERPK="{ORDERPK}">
        <xsl:apply-templates/>  
    </order>
</xsl:template>

<xsl:template match="JOB_x0020_NUMBER | ORDERPK"/>

</xsl:stylesheet>

XML Output

<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2014-12-15T14:45:35">
   <order JOB_NUMBER="S019191-9" ORDERPK="2">
      <job_description>TESTDATA</job_description>
      <order_qty>1900</order_qty>
      <finishing_style>PB</finishing_style>
      <depth>10</depth>
      <width>8</width>
      <cover_pagination>4</cover_pagination>
      <text_pagination>12</text_pagination>
      <delivery_commence_date>15/12/2014</delivery_commence_date>
      <delivery_complete_date>15/12/2014</delivery_complete_date>
      <job_site>DG</job_site>
      <managing_printer>DG</managing_printer>
      <is_managing_printer>TRUE</is_managing_printer>
      <cust_order_ref>776031</cust_order_ref>
      <cust_code>Test</cust_code>
      <site_cce_name>Jamie</site_cce_name>
      <site_cce_email>[email protected]</site_cce_email>
      <sales_person_name>Jamie Brace</sales_person_name>
      <sales_person_email>[email protected]</sales_person_email>
   </order>
</dataroot>

By the way, in your XML, there is a namespace declaration that is never used:

xmlns:od="urn:schemas-microsoft-com:officedata"

You might want to exclude it from the result. If you can use XSLT 2.0, you could use copy-namespaces="no" for that. In XSLT 1.0, you'd have to mimic copy-namespaces.

Upvotes: 1

Related Questions