XSL output XML unprefixed without using default namespace?

I have XSL where I need to generate output line by line:

<moo xmlns="http://api.example.com">
    <foo>1358944586848</foo>
    <bar>
        <a>1</a>
        <b>2</b>
        <c>3</c>
    </bar>
</moo>

      

I could do it like this:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://api.example.com">

    <xsl:template match="/">
        <xsl:element name="moo">
            <!-- and so on -->

      

However, I hate using the xsl prefix in my xsl files because I feel like it gets in the way of it. Choosing with XPath is easy, as you can set xpath-default-namespace

what you are converting to if necessary. But as far as I know, no element-default-namespace

, so how can I generate the desired output in a good way?

I know I can do this:

<stylesheet version="2.0"
    xmlns="http://www.w3.org/1999/XSL/Transform">

    <template match="/">
        <element name="moo" namespace="http://api.example.com">
            <!-- and so on -->

      

But then I have to set this namespace explicitly on every single element I create, or they will have an XSL namespace instead. So, is there a clean way to create elements with a specific namespace (no prefix) and not touch the default namespace for the xsl file?


Update:

Maybe namespace-alias

can do something but can't figure out how to use it. Tried this but doesn't seem to make any difference in the output:

<stylesheet version="2.0"
    xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:out="http://api.example.com">

<namespace-alias stylesheet-prefix="out" result-prefix=""/>

    <template match="/">
        <element name="out:moo">
            <!-- and so on -->

      

namespace-alias

thing probably doesn't do what i think: p

The last solution I used based on JLRishe's answer

remove-prefixes.xsl

<?xml version="1.0" encoding="UTF-8"?>
<stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform">
    <template match="/">
        <variable name="result">
            <next-match />
        </variable>
        <apply-templates select="$result" mode="remove-prefixes" />
    </template>

    <template match="*" priority="1" mode="remove-prefixes">
        <element name="{local-name()}" namespace="{namespace-uri()}">
            <apply-templates select="@* | node()" mode="remove-prefixes" />
        </element>
    </template>
    <template match="@*|node()" mode="remove-prefixes">
        <copy>
            <apply-templates select="@* | node()" mode="remove-prefixes" />
        </copy>
    </template>

</stylesheet>

      

subject.xsl

<!-- snip -->
<import href="remove-prefixes.xsl" />
<!-- snip -->

      

+3


source to share


3 answers


One thing you can do is grab the entire XSL result in a variable and then strip out its prefixes at the end:

<stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform"
                          xmlns:p="http://api.example.com">
  <output method="xml" indent="yes"/>

  <template match="/">
    <variable name="result">
      <p:moo>
        <apply-templates />
      </p:moo>
    </variable>
    <apply-templates select="$result" mode="removePrefix" />
  </template>

  <template match="root">
    <p:something hello="hi">
      <element name="p:somethingelse" />
    </p:something>
  </template>

  <template match="p:*" mode="removePrefix">
    <element name="{local-name()}" namespace="{namespace-uri()}">
      <apply-templates select="@* | node()" mode="removePrefix" />
    </element>
  </template>

  <template match="@* | node()" mode="removePrefix">
    <copy>
      <apply-templates select="@* | node()" />
    </copy>
  </template>
</stylesheet>

      

When run on this input:



<root>
  <top />
</root>

      

it produces:

<moo xmlns="http://api.example.com">
  <something hello="hi">
    <somethingelse />
  </something>
</moo>

      

+3


source


xmlns:xsl

-approach is indeed a "standard" day, and I assume that the XSL developers had this in mind.

Remember, you are allowed to mix XML fragments into XSL directly. From this point of view, your approach with xsl:element

perhaps adds a lot more noise and clutter than what you are trying to eliminate with your default namespace.

So, I would do this:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://api.example.com">

    <xsl:template match="/">
        <moo>
            <!-- and so on -->

      

Edit:



The following may work with namespace-alias

:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://api.example.com">

    <namespace-alias stylesheet-prefix="xsl" result-prefix="#default"/>

    <template match="/" xmlns="http://www.w3.org/1999/XSL/Transform">
        <element name="moo">
            <!-- etc -->

      

Or like this:

<stylesheet version="2.0"
    exclude-result-prefixes="api" 
    xmlns="http://www.w3.org/1999/XSL/Transform"
    xmlns:api="http://api.example.com">

    <namespace-alias stylesheet-prefix="#default" result-prefix="api"/>

    <template match="/">
        <element name="moo">
            <!-- etc -->

      

+1


source


I feel the same way you do about clutter, especially if I have stylesheets where the vast majority of the elements are in the XSL namespace and not in the target namespace. The solution is simple: prefix the output elements, not the XSL elements:

<stylesheet version="2.0"
    xmlns="http://www.w3.org/1999/XSL/Transform"
    xmlns:o="http://api.example.com">

    <template match="/">
        <o:moo>
            <!-- and so on -->

      

0


source







All Articles