0

I am doing a Schematron validation on an XML file and my result looks like this:

<fired-rule context="Message[@Name='SPY_IN']"/>
<failed-assert test="@OppositeMacAddress='0x00'" location="/Module[1]/Router[1]/Message[1]">
  <text>!Error! Erwarteter Wert:"0x00"</text>
</failed-assert>

<fired-rule context="Configuration[@Address='W_ST_PLAMA_MOD_OWM_OPP']"/>
<failed-assert test="@Name='8'"
  location="/Module[1]/DriverConfigurations[1]/DriverConfiguration[20]/Configuration[10]">
  <text>!Error! Erwarteter Wert:"8"</text>
</failed-assert>

Now i am trying to generate a XML file that referes to the "location"-attribute. It should look like this:

<Module>
  <Router>
    <Message>
    </Message>
  </Router>
</Module>
<Module>
  <DriverConfigurations>
    <DriverConfiguration>
      <Configuration>
      </Configuration>
    </DriverConfiguration>
  </DriverConfigurations>
</Module>

I tried to refer to this: auto creating xml elements using XSLT But it somehow doesnt work for me. So i have no idea how my xsl file should look like. Any idea?

1
  • Could you post your current XSLT? Commented Apr 2, 2013 at 17:06

1 Answer 1

1

Give this a try:

<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:element>
  </xsl:template>
</xsl:stylesheet>

When run on this input:

<root>
  <fired-rule context="Message[@Name='SPY_IN']"/>
  <failed-assert test="@OppositeMacAddress='0x00'" location="/Module[1]/Router[1]/Message[1]">
    <text>!Error! Erwarteter Wert:"0x00"</text>
  </failed-assert>

  <fired-rule context="Configuration[@Address='W_ST_PLAMA_MOD_OWM_OPP']"/>
  <failed-assert test="@Name='8'"
    location="/Module[1]/DriverConfigurations[1]/DriverConfiguration[20]/Configuration[10]">
    <text>!Error! Erwarteter Wert:"8"</text>
  </failed-assert>
</root>

The result is:

<root>
  <Module>
    <Router>
      <Message />
    </Router>
  </Module>
  <Module>
    <DriverConfigurations>
      <DriverConfiguration>
        <Configuration />
      </DriverConfiguration>
    </DriverConfigurations>
  </Module>
</root>
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks alot! It works great. Just one more question: why do i have to use the two <xsl:template match="/"> and <xsl:template match="@location"> tags? Would it be possible to pack them in one <xsl:template> tag?
No, I don't see any sensible way these could be combined into a single template, and it wouldn't make sense to do so. The first template is needed to pass processing on to all the location attributes, and the second actually handles them. If you actually have a more involved XSLT that you want to integrate the above into, then the first template may not be needed. If that's the case, perhaps you can open up a new question about how to combine this functionality into your existing XSLT.
Okay thanks! No actually i just wanted to understand what the code is doing.

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.