Wenn in einem Node kein Text ist, soll der Text eines anderen Nodes verwendet werden.
/ITEM/TEXT_SHORT[text()]/text() | /ITEM/TEXT_LONG[text() and not(/ITEM/TEXT_SHORT[text()])]/text()
Hier wird vorrangig der TEXT_SHORT verwendet. Sollte dieser aber leer sein, wird auf den TEXT_LONG zurück gegriffen.
Ich habe mir das auch aus anderen Beispielen so lange hin und her gebastelt bis es ging. Aber so erspart man sich zusätzlichen Code der später die beiden Texte abgleicht und es wird gleich richtig eingelesen.
User
annonyme
Date
2018-02-07 19:20
Tags
and not , beispiel , else , empty , example , hannes pries , if , node , parsen , text , xml , xpath
Wählt möglichst weit aus einander liegende Farben aus der Auswahl aller Farben, wobei die Enden (Schwarz und Weiß) ausgelassen werden. Da bei wenigen Farben nur Grautöne heraus kommen, werden bei weniger als 8 Farben die Abstände zwischen den Farben geringer als möglich gewählt.
function ColorGeneratorService(){
this.generateColorList = function(neededColorCount){
var minColorsfactor = 1;
if(neededColorCount < 8){
minColorsfactor = 3;
}
var result = [];
var end = parseInt(0xFFFFFF);
var step = Math.round(end / ((neededColorCount * minColorsfactor) + 1));
for(var i = 1; i <= neededColorCount; i++){
result[result.length] = "#"+(step * (i * minColorsfactor)).toString(16);
}
return result;
};
}
<div ng-reapeat="item in items">
{{$index}} - {{item.name}}
</div>
Wenn man mit Sub-Items arbeitet.
<ul>
<li ng-reapeat="item in items" ng-init="mainIndex=$index">
{{mainIndex}}. - {{item.name}}
<ul ng-if="item.subs && item.subs.length>0">
<li ng-repeat="sub in item.subs" ng-init="subIndex=$index">
{{mainIndex}}.{{subIndex}}. {{sub.name}}
</li>
</ul>
</li>
</ul>
Und komplett rekursiv.
<script type="text/ng-template" id="subs.html">
<li ng-repeat="item in parent.subs">
{{prefixIndex}}{{$index}}. {{item.name}}
<ul ng-if="item.subs && item.subs.length>0" ng-include="subs.html" ng-init="prefixIndex=prefixIndex+$index+'.'; parent=item">
</ul>
</li>
</scipt>
<ul ng-if="theRealParentItem.items && theRealParentItem.items.length>0" ng-include="subs.html" ng-init="prefixIndex=''; parent=theRealParentItem">
<ul>
Diese Übergabe an Werten ist auch im Zusammenspiel mit SVG sehr praktisch, weil man so Koordinaten nicht in den Objekten oder im Controller hinterlegen muss, sondern sie immer weiter durch reichen kann, um für jedes Level einen eigenen Ursprung definieren zu können.
Wer solche Diagramme mit dem Canvas Element und etwas Javascript zeichnen möchte, kann gerne diese von mir geschriebene Klasse verwenden:
function BarChartFactory(canvasElement,unitName,plotEvery){
this.canvas=canvasElement;
this.maxValue=0;
this.categoryTitleWidth=50;
this.valueTitleWidth=50;
this.bottomScalaHeight=10;
this.padding=5;
this.linesSeperateValues=true;
this.barStart=0;
this.barEnd=0;
this.barTranslationFactor=1;
this.barHeight=20;
this.barPadding=4; //top + bottom
this.xPlotEvery=plotEvery;
this.unitName=unitName;
this.categoryValueSize=2; //if more.. ignore.. if less.. paint empty
this.categories=[];
this.ctx=null;
this.width=200;
this.height=0;
this.addValue=function(categoryTitle,valueTitle,value,valueColor){
var cat=null;
for(var ii=0;ii<this.categories.length && cat==null;ii++){
if(this.categories[ii].title==categoryTitle){
cat=this.categories[ii];
console.log("found existing category: "+categoryTitle);
}
}
if(cat==null){
cat={title:"",values:[]};
cat.title=categoryTitle;
this.categories[this.categories.length]=cat;
}
cat.values[cat.values.length]={value:value,title:valueTitle,color:valueColor};
};
this.init=function(ctx,width){
this.barStart=this.categoryTitleWidth+this.valueTitleWidth;
this.barEnd=width;
for(var ii=0;ii<this.categories.length;ii++){
var cat=this.categories[ii];
for(var j=0;j<cat.values.length;j++){
if(cat.values[j].value>this.maxValue){
this.maxValue=cat.values[j].value;
}
}
if(cat.values.length>this.categoryValueSize){
this.categoryValueSize=cat.values.length;
}
}
this.maxValue=this.maxValue+(this.maxValue/10);
this.barTranslationFactor=(this.barEnd-this.barStart)/this.maxValue;
this.ctx=ctx;
this.ctx.canvas.width=width+(this.padding*2);
this.ctx.canvas.height=(this.categories.length*this.categoryValueSize*this.barHeight)+this.bottomScalaHeight+(this.padding*2);
this.width=this.ctx.canvas.width;
this.height=this.ctx.canvas.height;
//TODO clearRect
};
this.paintStructure=function(){
//paint main structure
this.ctx.strokeStyle="#AAAAAA";
this.ctx.beginPath();
this.ctx.moveTo(this.categoryTitleWidth+this.valueTitleWidth,0+this.padding);
this.ctx.lineTo(this.categoryTitleWidth+this.valueTitleWidth,this.height-this.barHeight+this.barPadding);
this.ctx.stroke();
if(this.xPlotEvery>0){
console.log("paint structure ("+this.maxValue+")");
var xStart=this.categoryTitleWidth+this.valueTitleWidth;
for(var i=this.xPlotEvery;i<this.maxValue;i=i+this.xPlotEvery){
this.ctx.beginPath();
this.ctx.moveTo(xStart+(i*this.barTranslationFactor),0+this.padding);
this.ctx.lineTo(xStart+(i*this.barTranslationFactor),this.height-this.barHeight+this.barPadding);
this.ctx.stroke();
this.ctx.fillStyle="#000000";
this.ctx.fillText(""+Math.round(i)+this.unitName,xStart+(i*this.barTranslationFactor), this.height-this.barHeight+this.barPadding+12);
}
}
};
this.paint=function(width){
this.init(this.canvas.getContext("2d"),width);
this.ctx.lineWidth=1;
this.ctx.strokeStyle="#000000";
this.paintStructure();
this.ctx.strokeStyle="#000000";
for(var iC=0;iC<this.categories.length;iC++){
var cat=this.categories[iC];
this.ctx.fillStyle="#000000";
this.ctx.fillText(cat.title,this.padding,(((iC)*this.categoryValueSize)+Math.round(this.categoryValueSize/2))*this.barHeight+this.padding);
for(var i=0;i<this.categoryValueSize;i++){
var value={value:0,title:"",color:"#FF0000"};
if(cat.values){
value=cat.values;
}
this.ctx.fillStyle="#000000";
this.ctx.fillText(value.title,this.categoryTitleWidth,((iC*this.categoryValueSize)+i+1)*this.barHeight);
//line under value title
this.ctx.beginPath();
if(i==this.categoryValueSize-1){
this.ctx.moveTo(this.padding,((iC*this.categoryValueSize)+i+1)*this.barHeight+this.padding);
}
else{
this.ctx.moveTo(this.categoryTitleWidth,((iC*this.categoryValueSize)+i+1)*this.barHeight+this.padding);
}
if(this.linesSeperateValues){
this.ctx.lineTo(this.width-this.padding,((iC*this.categoryValueSize)+i+1)*this.barHeight+this.padding);
}
else{
this.ctx.lineTo(this.categoryTitleWidth+this.valueTitleWidth,((iC*this.categoryValueSize)+i+1)*this.barHeight+this.padding);
}
this.ctx.stroke();
//paint real value
this.ctx.beginPath();
this.ctx.rect(this.categoryTitleWidth+this.valueTitleWidth,((iC*this.categoryValueSize)+i)*this.barHeight+this.padding+this.barPadding,value.value*this.barTranslationFactor,this.barHeight-(this.barPadding*2));
this.ctx.stroke();
this.ctx.fillStyle=value.color;
this.ctx.fill();
}
}
};
}
Das Beispiel zum Bild sieht dann so aus:
<html>
<head>
<title>2dbar test</title>
<script type="text/javascript" src="./BarChartFactory.js"></script>
</head>
<body>
<canvas id="can" style="border:1px solid #000000;border-radius:4px;">
</canvas>
<script type="text/javascript">
var bcf=new BarChartFactory(document.getElementById("can"),"fps",10);
bcf.addValue("386SX","16 Mhz",20,"#70B4B6");
bcf.addValue("386SX","25 Mhz",25,"#0000FF");
bcf.addValue("386DX","25 Mhz",40,"#70B4B6");
bcf.addValue("386DX","33 Mhz",60,"#70B4B6");
bcf.paint(400);
</script>
</body>
</html>