Reputation: 42
I think I am too stupid or whatever... but... how it is possible to transform a child node in a parent node if exist?
I have a xml file that looks like the following...
<?xml version="1.0"?>
<?xml-stylesheet href="template.xsl" type="text/xsl" ?>
<MainChapter RSKM-Language="" EDD-Version="" xmlns:fm="fctfmns.xml">
<Chapter>
<Bar/>
<Head UniqueID="CHDFFEJA">Sicherheit und Gewährleistung</Head>
<Chapter>
<Bar/>
<Head>
Erklärung der Sicherheitshinweise<MarkIdx fm:MarkerType="Index">Sicherheitshinweise</MarkIdx>
</Head>
<Para>
<BodyText>Alle Sicherheitshinweise in dieser Betriebsanleitung weisen den Bediener frühzeitig auf mögliche Gefahren für Leib und Leben, auf mögliche Schäden an der Maschine und an Beistellgeräten, sowie auf fehlerfreies, produktives Arbeiten hin.</BodyText>
<BodyText>Alle für den Bediener besonders wichtigen Stellen sind mit einem Warnzeichen versehen. Diese Informationen sind vom Bediener unbedingt zu lesen und zu befolgen.</BodyText>
</Para>
<Para>
<Head>Bedeutungen:</Head>
<Warning Class="Warning">
<Warningtable fm:NumRows="2" fm:NumCols="2" fm:ColWidths="5201588,22571176" fm:TblFormat="Warning_Warning">
<WarningHead fm:NumRows="1">
<WarningHeadRow fm:MaxHeight="66060288" fm:MinHeight="0">
<Signalword fm:NumCols="2" fm:ColRotation="0">
<Graphic>
<fm:Frame Type="1" Align="4" Offset="0" BaseLine="374744" Cropped="0" HasImgGroups="0" Pos="18318744,36680121,1204098,1075727,0" Style="15,15,65536,0" Color="Schwarz" Common="0,0,0,2,0,393216,6553600," GroupParent="0">
<fm:Inset File="I:\D-140027\D-140027\illustrationen\WARNUNG.eps" Dpi="0" Fixed="1" Flipped="0" Pos="58008,50622,1121246,995520,0" Style="15,15,65536,0" Color="Schwarz" Common="0,0,0,2,2,393216,6553600," GroupParent="0"/>
</fm:Frame>
</Graphic>WARNUNG
</Signalword>
</WarningHeadRow>
</WarningHead>
<WarningBody fm:NumRows="1">
<WarningBodyRow fm:MaxHeight="66060288" fm:MinHeight="0">
<WarningSymbol fm:LFTop="" fm:ColRotation="0">
<Graphic>
<fm:Frame Type="1" Align="4" Offset="0" BaseLine="1579877" Cropped="0" HasImgGroups="0" Pos="7066500,38123845,4629870,2523590,0" Style="15,15,65536,0" Color="Schwarz" Common="0,0,0,2,0,393216,6553600," GroupParent="0">
<fm:Inset File="I:\D-140027\D-140027\illustrationen\warning_y_electricity.eps" Dpi="0" Fixed="1" Flipped="0" Pos="980468,0,2668934,2348803,0" Style="15,7,65536,0" Color="Schwarz" Common="0,0,0,2,2,393216,6553600," GroupParent="0"/>
</fm:Frame>
</Graphic>
</WarningSymbol>
<WarningMessage fm:LFLeft="" fm:LFTop="" fm:ColRotation="0">
<BodyText>Elektrische Spannung! Lebensgefahr durch Stromschlag! Arbeiten an der Maschine, bei denen ein Abschalten des elektrischen Stroms in der Betriebsanleitung zwingend vorgeschrieben ist, muss:</BodyText>
<List>
<ListEntry>
<BodyText>entweder die Stromzuführung durch Abklemmen vom Netz oder Ziehen des Steckers unterbrochen werden,</BodyText>
</ListEntry>
</List>
<BodyText>oder:</BodyText>
<List>
<ListEntry>
<BodyText>der Hauptschalter gegen unbeabsichtigtes Einschalten gesichert werden. Dies kann mit einem Vorhängeschloss oder durch Anbringen einer Plombe am Schalter erfolgen.</BodyText>
</ListEntry>
</List>
</WarningMessage>
</WarningBodyRow>
</WarningBody>
</Warningtable>
</Warning>
</Para>
</Chapter>
</Chapter>
</MainChapter>
I am looking for a solution to loop trough each BodyText
in a WarningMessage
and if present, also through each ListEntry
if a List
node is present in the WarningMessage
as a child node, together with the BodyText
's.
A BodyText
is given in each WarningMessage
, but a List
is only sometimes given and can have in itself some ListEntry
's with one or more BodyText
's.
I have tryed something till now, but can not find a working solution for this issue.
The following solution does not what it should... I get only each BodyText
in a WarningMessage
, but it ignores the List
elements. I am trying to write a xsl:template solution who is able to transform the whole xml sentence to valid html/css.
Here is a picture of what I get and what I expect to get: http://i59.tinypic.com/33ma0qo.png
<xsl:template match="//WarningMessage/List" name="WarnList">
<ul>
<xsl:for-each select="ListEntry">
<li>
<xsl:for-each select="BodyText">
<xsl:value-of select="."/>
</xsl:for-each>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<!-- Warnungen vom Typ "Danger" -->
<xsl:template match="Warning[contains(concat(' ', @Class, ' '),' Danger ')]">
<div class="alert alert-danger" role="alert">
<h4><span class="glyphicon glyphicon-warning-sign"/><stong>
<xsl:value-of select="Warningtable/WarningHead/WarningHeadRow/Signalword"/>
</stong></h4>
<xsl:for-each select="Warningtable/WarningBody/WarningBodyRow/WarningMessage/BodyText">
<p>
<xsl:value-of select="."/>
<xsl:call-template name="WarnList"/>
</p>
</xsl:for-each>
</div>
</xsl:template>
Has anybody a hint how to write the xsl:template to get each BodyText
and if present, also each List
with each ListEntry
?
For clarification: it is possible that one WarningMessage includes one or more BodyText
, List
and ListEntry
.
I hope it is now clear what I want to reach... because it is a bit difficult for me to describe my issue.
If it is important for clarification, here is my whole xslt file... but I only need a solution to handle the List's and ListEntrys in the WarningMessage.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" doctype-system="about:legacy-compat" />
<xsl:template match="/">
<html>
<head>
<meta charset="utf-8" />
<title>Testausgabe</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet"></link>
<!-- Individual Theme CSS -->
<link href="css/theme.css" rel="stylesheet"></link>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="js/jquery.easing.js"></script>
</head>
<body>
<div class="topwrapper"></div>
<div class="wrapper">
<div class="container">
<div class="row">
<xsl:apply-templates />
</div><!-- end row -->
</div><!-- end container -->
</div><!-- end wrapper -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
<footer class="footer">
<div class="container">
<div class="row">
<img src="images/vc999_logo_94x40.png"></img>
</div>
</div>
</footer>
</body>
</html>
</xsl:template>
<xsl:template match="MarkIdx" mode="non-MarkIdx"/>
<!-- Header-Bars formatieren -->
<xsl:template match="Bar">
<hr/>
</xsl:template>
<!-- Hauptüberschrift [h1] formatieren -->
<xsl:template match="MainChapter/Chapter/Head">
<h1>
<xsl:value-of select="."/>
</h1>
</xsl:template>
<!-- Überschrift Ebene 2 [h2] formatieren -->
<xsl:template match="MainChapter/Chapter/Chapter/Head">
<h2>
<xsl:apply-templates select="." mode="non-MarkIdx"/>
</h2>
</xsl:template>
<!-- Überschrift Ebene 3 [h3] formatieren -->
<xsl:template match="//Para/Head | MainChapter/Chapter/Chapter/Chapter/Head">
<h3>
<xsl:apply-templates select="." mode="non-MarkIdx"/>
</h3>
</xsl:template>
<!-- Alle BodyText's direkt innerhalb eines Para formatieren -->
<xsl:template match="//Para/BodyText">
<p>
<xsl:value-of select="."/>
</p>
</xsl:template>
<!-- Listenelemente direkt innerhalb eines Para formatieren -->
<xsl:template match="//Para/List">
<ul class="list-group">
<xsl:for-each select="ListEntry">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">
<li class="list-group-item">
<xsl:value-of select="BodyText"/>
</li>
</xsl:when>
<xsl:otherwise>
<li class="list-group-item list-group-item-grey">
<xsl:value-of select="BodyText"/>
</li>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</ul>
</xsl:template>
<!-- Tabellen direkt innerhalb eines Para formatieren -->
<xsl:template match="//Para/Table">
<xsl:for-each select="InvisibleTable/TBody">
<table class="table table-striped">
<xsl:for-each select="TRow">
<tr>
<xsl:for-each select="TCell">
<td>
<xsl:for-each select="BodyText">
<span>
<xsl:value-of select="current()"/>
</span>
<br/>
</xsl:for-each>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:template>
<!-- Warnschilder direkt innerhalb eines Para formatieren -->
<!-- List's innerhalb einer Warning -->
<xsl:template match="//WarningMessage/List" name="WarnList">
<ul>
<xsl:for-each select="ListEntry">
<li>
<xsl:for-each select="BodyText">
<xsl:value-of select="."/>
</xsl:for-each>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<!-- Warnungen vom Typ "Danger" -->
<xsl:template match="Warning[contains(concat(' ', @Class, ' '),' Danger ')]">
<div class="alert alert-danger" role="alert">
<h4><span class="glyphicon glyphicon-warning-sign"/><stong>
<xsl:value-of select="Warningtable/WarningHead/WarningHeadRow/Signalword"/>
</stong></h4>
<xsl:for-each select="Warningtable/WarningBody/WarningBodyRow/WarningMessage/BodyText">
<p>
<xsl:value-of select="."/>
<xsl:call-template name="WarnList"/>
</p>
</xsl:for-each>
</div>
</xsl:template>
<!-- Warnungen vom Typ "Warning" -->
<xsl:template match="Warning[contains(concat(' ', @Class, ' '),' Warning ')]">
<div class="alert alert-warning" role="alert">
<h4>
<span class="glyphicon glyphicon-warning-sign"/>
<stong>
<xsl:value-of select="Warningtable/WarningHead/WarningHeadRow/Signalword"/>
</stong>
</h4>
<xsl:for-each select="Warningtable/WarningBody/WarningBodyRow/WarningMessage/BodyText">
<p>
<xsl:value-of select="."/>
</p>
</xsl:for-each>
</div>
</xsl:template>
<!-- Warnungen vom Typ "Caution" -->
<xsl:template match="//Para/Warning[contains(concat(' ', @Class, ' '),' Caution ')]">
<div class="alert alert-caution" role="alert">
<h4>
<span class="glyphicon glyphicon-warning-sign"/>
<stong>
<xsl:value-of select="Warningtable/WarningHead/WarningHeadRow/Signalword"/>
</stong>
</h4>
<xsl:for-each select="Warningtable/WarningBody/WarningBodyRow/WarningMessage/BodyText">
<p>
<xsl:value-of select="."/>
</p>
</xsl:for-each>
</div>
</xsl:template>
<!-- Infoschilder direkt innerhalb eines Para formatieren -->
<xsl:template match="//Para/Info">
<div class="alert alert-info" role="alert">
<h4>
<span class="glyphicon glyphicon-info-sign"/>
</h4>
<xsl:value-of select="./InfoGroup/InfoBody/InfoRow/InfoCell/BodyText"/>
</div>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Views: 372
Reputation: 22647
Simply change this line:
<xsl:for-each select="Warningtable/WarningBody/WarningBodyRow/WarningMessage/BodyText">
to:
<xsl:for-each select="Warningtable/WarningBody/WarningBodyRow/WarningMessage//BodyText">
The only change is the //
before BodyText
. Why? If you look at your input XML, only one BodyText
element is an immediate descendant of WarningMessage
. The others are inside List
and ListEntry
elements. Whereas /
as a separator means going down the "child::" axis, //
means finding all descendant BodyText
elements.
Then, the relevant part of the output will be:
<p>
Elektrische Spannung! Lebensgefahr durch Stromschlag! Arbeiten an der Maschine, bei denen ein Abschalten des elektrischen Stroms in der Betriebsanleitung zwingend vorgeschrieben ist, muss:
</p>
<p>entweder die Stromzuführung durch Abklemmen vom Netz oder Ziehen des Steckers unterbrochen werden,
</p>
<p>oder:</p>
<p>der Hauptschalter gegen unbeabsichtigtes Einschalten gesichert werden. Dies kann mit einem Vorhängeschloss oder durch Anbringen einer Plombe am Schalter erfolgen.
</p>
Please note:
//
and path expressions should not be overly long.EDIT (as a response to your comment)
Is it also possible to transform the ´List´ elements to ´ul´ tags and the
´ListEntry´ elements to ´li´ tags and display the ´BodyText´ between the ´<li>´
and ´</li>´ tag?
Yes, that's possible. But I recommend you restructure your code a bit. Start with the template that matches Warning
elements:
<xsl:template match="Warning[contains(concat(' ', @Class, ' '),' Warning ')]">
<div class="alert alert-warning" role="alert">
<h4>
<span class="glyphicon glyphicon-warning-sign"/>
<stong>
<xsl:value-of select="//Signalword"/>
</stong>
</h4>
<xsl:apply-templates/>
</div>
</xsl:template>
Then, write additional templates that match List
:
<xsl:template match="List">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>
One that matches ListEntry
:
<xsl:template match="ListEntry">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
And finally, one that matches BodyText
:
<xsl:template match="BodyText">
<p>
<xsl:value-of select="."/>
</p>
</xsl:template>
As you can see, I do not use for-each
because it is absolutely not necessary. Instead, there are separate template rules for all elements. That should bring order into your code.
Upvotes: 1