Index: src/org/openstreetmap/josm/gui/mappaint/BoxTextElemStyle.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/BoxTextElemStyle.java	(revision 4638)
+++ src/org/openstreetmap/josm/gui/mappaint/BoxTextElemStyle.java	(working copy)
@@ -7,6 +7,7 @@
 import java.awt.Rectangle;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPainter;
 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
@@ -102,6 +103,11 @@
     public void paintPrimitive(OsmPrimitive osm, MapPaintSettings settings, MapPainter painter, boolean selected, boolean member) {
         if (osm instanceof Node) {
             painter.drawBoxText((Node) osm, this);
+        } else if (osm instanceof Way) {
+            // DEMO: use middle node for displaying way symbol text (shield)
+            Way way = (Way)osm;
+            Node node = way.getNode((int)Math.floor(way.getNodesCount() / 2));
+            painter.drawBoxText(node, this);
         }
     }
 
Index: src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 4638)
+++ src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(working copy)
@@ -311,7 +311,15 @@
                 addIfNotNull(sl, LinePatternElemStyle.create(env));
                 addIfNotNull(sl, LineElemStyle.createLine(env));
                 addIfNotNull(sl, LineElemStyle.createCasing(env));
-                addIfNotNull(sl, LineTextElemStyle.create(env));
+
+                // DEMO: allow node styles (icon or symbol) on ways, handling in NodeElemStyle.paintPrimitive
+                NodeElemStyle nodeStyle = NodeElemStyle.create(env);
+                if (nodeStyle != null) {
+                    addIfNotNull(sl, NodeElemStyle.create(env));
+                    addIfNotNull(sl, BoxTextElemStyle.create(env, nodeStyle.getBox()));
+                } else {
+                    addIfNotNull(sl, LineTextElemStyle.create(env));
+                }
             } else if (osm instanceof Node) {
                 NodeElemStyle nodeStyle = NodeElemStyle.create(env);
                 if (nodeStyle != null) {
Index: src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 4638)
+++ src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(working copy)
@@ -15,6 +15,7 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
 import org.openstreetmap.josm.data.osm.visitor.paint.MapPainter;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
@@ -238,8 +239,16 @@
 
     @Override
     public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings settings, MapPainter painter, boolean selected, boolean member) {
-        if (primitive instanceof Node) {
-            Node n = (Node) primitive;
+        if (primitive instanceof Node || primitive instanceof Way) {
+            Node n;
+            if (primitive instanceof Way) {
+                // DEMO: use middle node for displaying way icon/symbol (shield)
+                Way way = (Way) primitive;
+                n = way.getNode((int)Math.floor(way.getNodesCount() / 2));
+            } else {
+                n = (Node) primitive;
+            }
+
             if (icon != null && painter.isShowIcons()) {
                 painter.drawNodeIcon(n, (painter.isInactiveMode() || n.isDisabled()) ? getDisabledIcon() : icon,
                         Utils.color_int2float(iconAlpha), selected, member);
Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 4638)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(working copy)
@@ -10,6 +10,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.search.SearchCompiler;
@@ -18,6 +20,7 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.mappaint.Cascade;
 import org.openstreetmap.josm.gui.mappaint.Environment;
+import org.openstreetmap.josm.gui.mappaint.Keyword;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -139,6 +142,31 @@
                 return prop(key, null);
             }
 
+            public Keyword color(String color) {
+                return new Keyword(color);
+            }
+
+            public String regex(String pattern, Object value) {
+                Pattern p = Pattern.compile(pattern);
+                Matcher m = p.matcher((String)value);
+                if (m.find())
+                    return m.group(1);
+                else
+                    return null;
+            }
+
+            // allows global properties by setting properties of a different layer
+            public Object set_prop(String key, String layer, Object value) {
+                Cascade c;
+                if (layer == null) {
+                    c = env.mc.getCascade(env.layer);
+                } else {
+                    c = env.mc.getCascade(layer);
+                }
+                c.put(key, value);
+                return value;
+            }
+
             public Object prop(String key, String layer) {
                 Cascade c;
                 if (layer == null) {
Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 4638)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(working copy)
@@ -18,6 +18,7 @@
 import org.openstreetmap.josm.gui.mappaint.MultiCascade;
 import org.openstreetmap.josm.gui.mappaint.Range;
 import org.openstreetmap.josm.gui.mappaint.StyleSource;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
 import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser;
 import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.ParseException;
@@ -154,33 +155,42 @@
         for (MapCSSRule r : rules) {
             for (Selector s : r.selectors) {
                 env.clearSelectorMatchingInformation();
-                if (s.matches(env)) { // as side effect env.parent will be set (if s is a child selector)
-                    if (s.getRange().contains(scale)) {
-                        mc.range = Range.cut(mc.range, s.getRange());
-                    } else {
-                        mc.range = mc.range.reduceAround(scale, s.getRange());
-                        continue;
+                if (s instanceof ChildOrParentSelector) {
+                    // loop allows selector to iterate over all matching parents/children and execute for each
+                    while(s.matches(env)) {
+                        execute(r, s, env, mc, scale);
                     }
+                } else if (s.matches(env)) { // as side effect env.parent will be set (if s is a child selector)
+                    execute(r, s, env, mc, scale);
+                }
+            }
+        }
+    }
 
-                    String sub = s.getSubpart();
-                    if (sub == null) {
-                        sub = "default";
-                    }
+    private void execute(MapCSSRule r, Selector s, Environment env, MultiCascade mc, double scale) {
+        if (s.getRange().contains(scale)) {
+            mc.range = Range.cut(mc.range, s.getRange());
+        } else {
+            mc.range = mc.range.reduceAround(scale, s.getRange());
+            return;
+        }
 
-                    if (sub.equals("*")) {
-                        for (Entry<String, Cascade> entry : mc.getLayers()) {
-                            env.layer = entry.getKey();
-                            if (Utils.equal(env.layer, "*")) {
-                                continue;
-                            }
-                            r.execute(env);
-                        }
-                    }
-                    env.layer = sub;
-                    r.execute(env);
+        String sub = s.getSubpart();
+        if (sub == null) {
+            sub = "default";
+        }
+
+        if (sub.equals("*")) {
+            for (Entry<String, Cascade> entry : mc.getLayers()) {
+                env.layer = entry.getKey();
+                if (Utils.equal(env.layer, "*")) {
+                    continue;
                 }
+                r.execute(env);
             }
         }
+        env.layer = sub;
+        r.execute(env);
     }
 
     @Override
Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(revision 4638)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(working copy)
@@ -5,7 +5,6 @@
 
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
@@ -53,6 +52,8 @@
          */
         private final boolean parentSelector;
 
+        private int iterationIndex = -1;
+
         /**
          * 
          * @param a the first selector
@@ -79,6 +80,7 @@
          */
         private  class MatchingReferrerFinder extends AbstractVisitor{
             private Environment e;
+            public boolean matched = false;
 
             /**
              * Constructor
@@ -122,8 +124,17 @@
                  * If e.parent is already set to the first matching referrer. We skip any following
                  * referrer injected into the visitor.
                  */
-                if (e.parent != null) return;
+                //if (e.parent != null) return;
+                if (matched) return;
 
+                // skip until after previous match
+                if (e.parent != null) {
+                    if (e.parent.equals(r)) {
+                        e.parent = null;
+                    }
+                    return;
+                }
+
                 if (!left.matches(e.withPrimitive(r)))
                     return;
                 for (int i=0; i < r.getMembersCount(); i++) {
@@ -132,6 +143,7 @@
                         if (link.matches(e.withParent(r).withIndex(i).withLinkContext())) {
                             e.parent = r;
                             e.index = i;
+                            matched = true;
                             return;
                         }
                     }
@@ -147,8 +159,14 @@
             if (!parentSelector) {
                 MatchingReferrerFinder collector = new MatchingReferrerFinder(e);
                 e.osm.visitReferrers(collector);
-                if (e.parent != null)
-                    return true;
+
+                if (collector.matched) {
+                    iterationIndex++;
+                } else {
+                    iterationIndex = -1;
+                }
+
+                return collector.matched;
             } else {
                 if (e.osm instanceof Way) {
                     List<Node> wayNodes = ((Way) e.osm).getNodes();
@@ -182,7 +200,9 @@
 
         @Override
         public String getSubpart() {
-            return right.getSubpart();
+        	// dynamic layer names for multiple declaration executions
+            String result = (iterationIndex > -1 ? right.getSubpart() + iterationIndex : right.getSubpart());
+            return result;
         }
 
         @Override
