1

I have something like this

<a>
    <b>
        <c>1</c>
        <d>2<e>3</e></d>
    </b>
</a>

and I want to obtain a sequence like this

<a/>
<b/>
<c>1</c>
<d>2<e>3</e></d>

that is, when recursing, every time an element occurs which does not have a text node, I want to output the element as an empty element, whereas every time an element with a text node occurs, I want to output it as it is. Of course, the text nodes in the above input have to be space-normalized.

If I put it through a standard identity transform,

declare function local:copy($element as element()) as element() {
   element {node-name($element)}
      {$element/@*,
          for $child in $element/*
              return
                  if ($child/text())
                  then $child
                  else (element {node-name($child)}{$child/@*}, local:copy($child))
      }
};

<b> gets reconstructed as a full element (containing <c> and <d>), but if I remove the element constructor, it does not get output at all.

1 Answers1

1

I don't quite get the fourth line in your example output, I'm just guessing what you want is actually this:

<a/>
<b/>
<c>1</c>
<d>2</d>
<e>3</e>

You don't need any functions. Just list all elements, reconstruct one with same name and include it's text node children.

for $element in //*
return element { local-name($element) } { $element/text() }

This version is even shorter, but I think it requires XQuery 3.0, because earlier versions did not allow element constructors in step expressions:

//*/element { local-name(.) } { text() }
Jens Erat
  • 37,523
  • 16
  • 80
  • 96