1

I am trying to add the "test" element into the last element of the tree, but it repeats for each element:

<root>
   <Module>
      <Router>
         <Message>@OppositeMacAddress='0x00, 0x80, 0xC8, 0x3B, 0xC6, 0xA0'</Message>
         @OppositeMacAddress='0x00, 0x80, 0xC8, 0x3B, 0xC6, 0xA0'
      </Router>
      @OppositeMacAddress='0x00, 0x80, 0xC8, 0x3B, 0xC6, 0xA0'
   </Module> 
</root>

This is my XML source

   <fired-rule context="Message[@Name='SPY_IN']"/>
       <failed-assert
               test="@OppositeIpAddress='192,168,1,2'"
               location="/Module[1]/Router[1]/Message[1]">
       <text>!Error! Erwarteter Wert:"192,168,1,2"</text>
   </failed-assert>

It should look like this:

<root>
   <Module>
      <Router>
         <Message>@OppositeMacAddress='0x00, 0x80, 0xC8, 0x3B, 0xC6, 0xA0'</Message>
      </Router>
   </Module>
</root>

And this is my XSL Transformation

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

  <xsl:template match="/">
    <root>
      <xsl:apply-templates select="//failed-assert/@location" />
    </root>
  </xsl:template>

  <xsl:template match="@location">
    <xsl:param name="path" select="." />

    <xsl:variable
        name="currentContext" 
        select="substring-before(substring-after($path,'/'), '[')"/>

    <xsl:variable name="subContext" select="substring-after($path, ']')"/>

    <xsl:element name="{$currentContext}">
      <xsl:apply-templates select="current()[string($subContext)]">
        <xsl:with-param name="path" select="$subContext"/>
      </xsl:apply-templates>
      <xsl:value-of select="../@test"/>
    </xsl:element>

  </xsl:template>

</xsl:stylesheet>

How can i solve this problem?

2 Answers 2

1

Try this inside your xsl:element:

  <xsl:variable name="next" select="current()[string($subContext)]" />

  <xsl:apply-templates select="$next">
    <xsl:with-param name="path" select="$subContext"/>
  </xsl:apply-templates>

  <xsl:value-of select="../@test[not($next)]"/>

Full XSLT:

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

  <xsl:template match="/">
    <root>
      <xsl:apply-templates select="//failed-assert/@location" />
    </root>
  </xsl:template>

  <xsl:template match="@location">
    <xsl:param name="path" select="." />

    <xsl:variable name="currentContext"
                  select="substring-before(substring-after($path,'/'), '[')"/>
    <xsl:variable name="subContext" select="substring-after($path, ']')"/>
    <xsl:element name="{$currentContext}">
      <xsl:variable name="next" select="current()[string($subContext)]" />

      <xsl:apply-templates select="$next">
        <xsl:with-param name="path" select="$subContext"/>
      </xsl:apply-templates>

      <xsl:value-of select="../@test[not($next)]"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Result when run on your sample input:

<root>
  <Module>
    <Router>
      <Message>@OppositeIpAddress='192,168,1,2'</Message>
    </Router>
  </Module>
</root>
Sign up to request clarification or add additional context in comments.

Comments

1

I think a little bit more understandable solution could be to use call-template.

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

    <xsl:template match="/">
        <root>
            <xsl:apply-templates select="//failed-assert[@location]" />
        </root>
    </xsl:template>

    <xsl:template match="failed-assert">
        <xsl:call-template name="location">
            <xsl:with-param name="path" select="substring-after(@location, '/')" />
            <xsl:with-param name="textmessage" select="@test" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="location">
        <xsl:param name="path" />
        <xsl:param name ="textmessage" />

        <xsl:variable name="currentContext"
                      select="substring-before($path,'[')"/>

        <xsl:variable name="subContext" select="substring-after($path, '/')"/>
        <xsl:choose>
            <xsl:when test="$currentContext">
                <xsl:element name="{$currentContext}">
                    <xsl:call-template name="location">
                        <xsl:with-param name="path" select="$subContext" />
                        <xsl:with-param name="textmessage" select="$textmessage" />
                    </xsl:call-template>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$textmessage"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.