0

I have the following XML, and would like to remove all ele tags, before numbering the x attribute of the ph elements that reside within some of these ele tags:

  <?xml version="1.0" encoding="UTF-8"?>
   <tmx version="1.4">
 <body>
    <tu>
        <prop type="x-Context">-2050338055591740051, -2050338055591740051</prop>
        <prop type="x-Origin">TM</prop>
        <prop type="x-ConfirmationLevel">Translated</prop>
        <tuv>
            <seg>
                <ele>The text </ele>
                <ele>
                    <ph x="0" type="QIAsymphony"/>
                </ele>
                <ele> goes </ele>
                <ele>
                    <ph x="0" type="470"/>
                </ele>
                <ele> here </ele>
                <ele>
                    <ph x="0" type="471"/>
                </ele>
                <ele>.</ele>
            </seg>
        </tuv>
        <tuv>
            <seg>
                <ele>El texto </ele>
                <ele>
                    <ph x="0" type="QIAsymphony"/>
                </ele>
                <ele> se mete </ele>
                <ele>
                    <ph x="0" type="471"/>
                </ele>
                <ele> aquí </ele>
                <ele>
                    <ph x="0" type="470"/>
                </ele>
                <ele>.</ele>
            </seg>
        </tuv>
    </tu>
 </body>
  </tmx>

I have the following XSLT, that performs the numbering operation, although I'm not sure what changes to make to replace the missing ele tags, once this element has been deleted from the XML:

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

 <xsl:key name="ph" match="tuv[1]/seg/ele/ph" use="@type" />

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

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

 <xsl:template match="tuv/seg/ele/ph/@x">
    <xsl:attribute name="x">
        <xsl:value-of select="count(key('ph', ../@type)/../preceding-sibling::ele[ph]) + 1" />
    </xsl:attribute>
</xsl:template>
</xsl:stylesheet>

Desired output:

<tuv>
    <seg>The text 
        <ph x="1" type="QIAsymphony"/> 
        goes 
        <ph x="3" type="471"/> 
        here 
        <ph x="2" type="470"/>
        . 
    </seg>
</tuv>
Kokkie
  • 546
  • 6
  • 15
  • I don't understand the question - your current XSLT doesn't remove anything, it just adjusts the `x` attribute of the `ph` elements. It might be clearer if you could edit the question and add a sample of the output you _want_ to produce so we can see more clearly what needs to change. – Ian Roberts Sep 03 '14 at 13:43
  • I'll rephrase. I would like to be able to perform this numbering operation on the above XML, but after all tags have been removed. I would like to know what changes I need to make to the above XSLT in order to achieve this. – user3289842 Sep 03 '14 at 14:19
  • Here's (part of) the desired output: El texto se mete aquí . – user3289842 Sep 03 '14 at 14:22
  • 1
    Please don't post code in comments as the formatting is lost. Instead _edit_ the original question (using the "edit" link under the tags) and put it in there as a proper code block. You can always edit your own posts, and as you gain reputation you'll eventually be able to edit other people's posts too. – Ian Roberts Sep 03 '14 at 14:49

1 Answers1

3

In the comments you say you want to remove the <ele> elements, but not their contents.

Because your XSLT is already based on the identity transform, that's easily done by adding a very simple template:

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

This template simply reads as: "When encountering <ele>, do not output anything but process its children". In effect <ele> is removed from the output, its children remain.

In context:

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

  <xsl:key name="ph" match="tuv[1]/seg/ele/ph" use="@type" />

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

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

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

  <xsl:template match="tuv/seg/ele/ph/@x">
    <xsl:attribute name="x">
      <xsl:value-of select="count(key('ph', ../@type)/../preceding-sibling::ele[ph]) + 1" />
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

Result:

<tmx version="1.4">
  <body>
    <tu>
      <prop type="x-Context">-2050338055591740051, -2050338055591740051</prop>
      <prop type="x-Origin">TM</prop>
      <prop type="x-ConfirmationLevel">Translated</prop>
      <tuv>
        <seg>The text <ph x="1" type="QIAsymphony"/> goes <ph x="2" type="470"/> here <ph x="3" type="471"/>.</seg>
      </tuv>
      <tuv>
        <seg>El texto <ph x="1" type="QIAsymphony"/> se mete <ph x="3" type="471"/> aquí <ph x="2" type="470"/>.</seg>
      </tuv>
    </tu>
  </body>
</tmx>
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Suppose I have more than one "tu" node: how would I get this to work on a node-by-node basis, ignoring occurrences of "ph" element "type" attribute values in other "tu" nodes? – user3289842 Sep 09 '14 at 09:08
  • You must make the `` node ID part of the key. Currently all `` are grouped by their `@type`, regardless of their location in the document. To make a separate group for each ``, use this expression as the key: `concat(@type, '|', generate-id(ancestor::tu[1]))`. (If you're not sure how XSL keys work in the first place, [read the lower part of this answer here](http://stackoverflow.com/a/955527/18771).) – Tomalak Sep 09 '14 at 09:18
  • Thanks for your input, but I can't make sense of the answer in the link provided. I'm not even sure where the key expression should go. – user3289842 Sep 09 '14 at 12:40
  • What I did not specify above, is that I want to limit numbering of ph element x attributes to the context of each current tu node. That is to say, that in the event of other tu nodes containing ph elements with a matching type attribute value, these are also currently being counted. How do I limit the operation to the current tu node only? – user3289842 Sep 15 '14 at 14:35
  • 1
    Did you read the *lower* part of the linked answer (i.e., *below* the horizontal rule)? It's really quite straight-forward as far as explanations of `` go. You have been using a key in your original code, after all. Now, I could say *"go to that line, replace this bit with that bit and it will start to work"*, but there isn't very much to learn from that, is there? So I'm not going to do it. I think you should read my comment above (and maybe the linked answer, too) again. The solution is right there, and it's not tricky, either. Sorry for not playing along quite so easily. :) – Tomalak Sep 15 '14 at 15:45
  • Yes, I've read it over and over again, and still don't get it. Sorry, but some people have an aptitude for these things; many of us, alas, have to blunder our way through :( – user3289842 Sep 17 '14 at 09:27