AutomatedChaos
AutomatedChaos

Reputation: 7490

Adding a namespace in the root element for use in attribute of child element

I have the following output from JUnit:

<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="Some Collection" tests="13" time="1.174">
  <testsuite name="Request 1"/>
  <testsuite name="Request 2">
    <testcase name="Status code is 200" time="0.083"/>
  </testsuite>
  <testsuite name="Request 3">
    <testcase name="Status code is 200" time="0.056"/>
    <testcase name="Validation message is triggered" time="0.056"/>
  </testsuite>
<testsuites>

In this case testsuites is my root element. In order to convert it correctly into JSON, I need to add the following attribute to the testsuite and testcase elements: json:Array="true", I do that with an XSL:

<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:json="http://james.newtonking.com/projects/json">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="//testsuite">
  <xsl:copy>
   <xsl:attribute name="json:Array">true</xsl:attribute> 
   <xsl:apply-templates select="node()|@*" /> 
  </xsl:copy>
 </xsl:template>

 <xsl:template match="//testcase">
  <xsl:copy>
   <xsl:attribute name="json:Array">true</xsl:attribute> 
   <xsl:apply-templates select="node()|@*" /> 
  </xsl:copy>
 </xsl:template>
</xsl:transform>

This results in the following (valid) xml:

<testsuites name="Some Collection" tests="13" time="1.174">
  <testsuite xmlns:json="http://james.newtonking.com/projects/json" json:Array="true" name="Request 1"/>
  <testsuite xmlns:json="http://james.newtonking.com/projects/json" json:Array="true" name="Request 2">
    <testcase xmlns:json="http://james.newtonking.com/projects/json" json:Array="true" name="Status code is 200" time="0.083"/>
  </testsuite>
  <testsuite xmlns:json="http://james.newtonking.com/projects/json" json:Array="true" name="Request 3">
    <testcase xmlns:json="http://james.newtonking.com/projects/json" json:Array="true" name="Status code is 200" time="0.056"/>
    <testcase xmlns:json="http://james.newtonking.com/projects/json" json:Array="true" name="Validation message is triggered" time="0.056"/>
  </testsuite>
<testsuites>

but what I really want is the namespace moved to the root element so it can be used in child elements:

<testsuites xmlns:json="http://james.newtonking.com/projects/json" name="Some Collection" tests="13" time="1.174">
  <testsuite json:Array="true" name="Request 1"/>
  <testsuite json:Array="true" name="Request 2">
    <testcase json:Array="true" name="Status code is 200" time="0.083"/>
  </testsuite>
  <testsuite json:Array="true" name="Request 3">
    <testcase json:Array="true" name="Status code is 200" time="0.056"/>
    <testcase json:Array="true" name="Validation message is triggered" time="0.056"/>
  </testsuite>
<testsuites>

How can I achieve that with XSLT?

Upvotes: 0

Views: 145

Answers (1)

Vebbie
Vebbie

Reputation: 1695

You just need to add an template matching the parent element testsuites like below:

<xsl:transform version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:json="http://james.newtonking.com/projects/json">
    <xsl:output omit-xml-declaration="yes" indent="yes" />

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

    <xsl:template match="//testsuite">
        <xsl:copy>
            <xsl:attribute name="json:Array">true</xsl:attribute>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//testcase">
        <xsl:copy>
            <xsl:attribute name="json:Array">true</xsl:attribute>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//testsuites">
        <testsuites xmlns:json="http://james.newtonking.com/projects/json">
            <xsl:apply-templates select="node()|@*" />
        </testsuites>
    </xsl:template>
</xsl:transform>

http://xsltransform.net/asnmyQ

Upvotes: 1

Related Questions