diff --git a/src/uk/me/parabola/mkgmap/osmstyle/ActionRule.java b/src/uk/me/parabola/mkgmap/osmstyle/ActionRule.java
index 91bdbee..493d32d 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/ActionRule.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/ActionRule.java
@@ -52,12 +52,27 @@ public class ActionRule implements Rule {
 		this.type = null;
 	}
 
+	public GType resolveType(Element el) {
+		return resolveType(el, null);
+	}
+
 	public GType resolveType(Element el, GType pre) {
 		if (expression == null || expression.eval(el)) {
-			for (Action a : actions)
-				a.perform(el);
+			if (type == null ||	pre == null || pre.isBetterPriority(type)) {
+				// this is the first (or only) time this rule has
+				// matched so execute the actions associated with the
+				// rule
+				for (Action a : actions)
+					a.perform(el);
 
-			return type;
+				return type;
+			}
+			else if(type.alwaysExecuteActions()) {
+				// this is not the first time the rule has matched but
+				// the user wants the actions executed anyway
+				for (Action a : actions)
+					a.perform(el);
+			}
 		}
 		return null;
 	}
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java b/src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java
index b7b5248..623f2d5 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java
@@ -36,6 +36,10 @@ public class ExpressionRule implements Rule {
 		this.gtype = gtype;
 	}
 
+	public GType resolveType(Element el) {
+		return resolveType(el, null);
+	}
+
 	public GType resolveType(Element el, GType pre) {
 		if (expression.eval(el))
 			return gtype;
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/FixedRule.java b/src/uk/me/parabola/mkgmap/osmstyle/FixedRule.java
index 315c4ad..4ea40ed 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/FixedRule.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/FixedRule.java
@@ -32,6 +32,10 @@ public class FixedRule implements Rule {
 		this.gtype = gtype;
 	}
 
+	public GType resolveType(Element el) {
+		return gtype;
+	}
+
 	public GType resolveType(Element el, GType pre) {
 		return gtype;
 	}
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java b/src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java
index 33ce15e..6e39800 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java
@@ -63,6 +63,10 @@ public class RuleSet implements Rule {
 		return rules.entrySet();
 	}
 
+	public GType resolveType(Element el) {
+		return resolveType(el, null);
+	}
+
 	public GType resolveType(Element el, GType pre) {
 		GType foundType = null;
 		for (String tagKey : el) {
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/SequenceRule.java b/src/uk/me/parabola/mkgmap/osmstyle/SequenceRule.java
index 72b5a59..8430f74 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/SequenceRule.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/SequenceRule.java
@@ -34,6 +34,10 @@ import uk.me.parabola.mkgmap.reader.osm.Rule;
 public class SequenceRule implements Rule, Iterable<Rule> {
 	private final List<Rule> ruleList = new ArrayList<Rule>();
 
+	public GType resolveType(Element el) {
+		return resolveType(el, null);
+	}
+
 	public GType resolveType(Element el, GType pre) {
 		for (Rule r : ruleList) {
 			GType type = r.resolveType(el, pre);
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index abc8941..d314fd4 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -276,20 +276,21 @@ public class StyledConverter implements OsmConverter {
 			preConvertRules(way);
 
 			do {
-				foundType = wayRules.resolveType(way, foundType);
+				Way dupWay = way.duplicate();
+				foundType = wayRules.resolveType(dupWay, foundType);
 				if (foundType == null)
 					return;
 
-				postConvertRules(way, foundType);
+				postConvertRules(dupWay, foundType);
 
 				if (foundType.getFeatureKind() == GType.POLYLINE) {
 					if(foundType.isRoad())
-						addRoad(way, foundType);
+						addRoad(dupWay, foundType);
 					else
-						addLine(way, foundType);
+						addLine(dupWay, foundType);
 				}
 				else
-					addShape(way, foundType);
+					addShape(dupWay, foundType);
 			} while (!foundType.isFinal());
 		}
 	}
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/TypeReader.java b/src/uk/me/parabola/mkgmap/osmstyle/TypeReader.java
index 0c5c193..f5a67af 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/TypeReader.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/TypeReader.java
@@ -62,6 +62,8 @@ public class TypeReader {
 				gt.setContinue();
 			} else if (w.equals("stop")) {
 				gt.setFinal();
+			} else if (w.equals("with_actions") || w.equals("withactions")) {
+				gt.alwaysExecuteActions(true);
 			} else {
 				throw new SyntaxException(ts, "Unrecognised type command '" + w + '\'');
 			}
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/GType.java b/src/uk/me/parabola/mkgmap/reader/osm/GType.java
index 9df318d..5f66256 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/GType.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/GType.java
@@ -62,6 +62,10 @@ public class GType {
 	// the final conversion, or whether we shall search
 	// for further matching elements
 	private boolean FinalElement = true;
+	// by default, a rule's actions are skipped when searching for
+	// further rules to match - by setting this true, the rule's
+	// actions will always be executed
+	private boolean alwaysExecuteActions = false;
 	
 	public GType(int featureKind, String type) {
 		priority = nextPriority();
@@ -202,6 +206,14 @@ public class GType {
 	public void setContinue() {
 		FinalElement = false;
 	}
+
+	public void alwaysExecuteActions(boolean aea) {
+		alwaysExecuteActions = aea;
+	}
+
+	public boolean alwaysExecuteActions() {
+		return alwaysExecuteActions;
+	}
 	
 	public boolean isFinal() {
 		return FinalElement;
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/Rule.java b/src/uk/me/parabola/mkgmap/reader/osm/Rule.java
index b709c67..f712e59 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/Rule.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/Rule.java
@@ -29,6 +29,15 @@ public interface Rule {
 	 * represent it.
 	 *
 	 * @param el The element as read from an OSM xml file in 'tag' format.
+	 * @return Enough information to represent this as a garmin type.
+	 */
+	public GType resolveType(Element el);
+
+	/**
+	 * Given the element return the garmin type that should be used to
+	 * represent it.
+	 *
+	 * @param el The element as read from an OSM xml file in 'tag' format.
 	 * @param pre The previous garmin type generated from the element.
 	 * @return Enough information to represent this as a garmin type.
 	 */
