You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2022/10/25 11:44:01 UTC

[sling-org-apache-sling-xss] branch master updated: SLING-11592 - Fix policy adapter condition chaining and add tests (#30)

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-xss.git


The following commit(s) were added to refs/heads/master by this push:
     new a657c91   SLING-11592 - Fix policy adapter condition chaining and add tests (#30)
a657c91 is described below

commit a657c91ef890aaddee92d92c10506b54e536b643
Author: Tatyana <36...@users.noreply.github.com>
AuthorDate: Tue Oct 25 13:43:57 2022 +0200

     SLING-11592 - Fix policy adapter condition chaining and add tests (#30)
    
    * Add tests for the dynamic and global attribute
    * Correct the policy adapter so that the conditions are added with an "or" instead of an "and".
    * Lowercase Attribute, Property and Tag names after parsing from config
    * Extract TestInput Class
    * Turn AntiSamyConfigLocale class into a static inner class
    * Remove unused imports
---
 .../sling/xss/impl/AntiSamyPolicyAdapter.java      |   76 +-
 .../org/apache/sling/xss/impl/XSSFilterImpl.java   |    3 +-
 .../apache/sling/xss/impl/xml/AntiSamyRules.java   |    9 +
 .../org/apache/sling/xss/impl/xml/Attribute.java   |    3 +-
 .../org/apache/sling/xss/impl/xml/MapBuilder.java  |   16 +-
 .../org/apache/sling/xss/impl/xml/Property.java    |    3 +-
 .../java/org/apache/sling/xss/impl/xml/Tag.java    |    6 +-
 .../apache/sling/xss/impl/AntiSamyPolicyTest.java  |   86 +-
 ...thAdditionalGlobalAndDynamicConditionsTest.java |   78 +
 .../java/org/apache/sling/xss/impl/TestInput.java  |   95 +
 ...figWithAdditionalGlobalAndDynamicConditions.xml | 2860 ++++++++++++++++++++
 11 files changed, 3097 insertions(+), 138 deletions(-)

diff --git a/src/main/java/org/apache/sling/xss/impl/AntiSamyPolicyAdapter.java b/src/main/java/org/apache/sling/xss/impl/AntiSamyPolicyAdapter.java
index bacb4f9..cb20842 100644
--- a/src/main/java/org/apache/sling/xss/impl/AntiSamyPolicyAdapter.java
+++ b/src/main/java/org/apache/sling/xss/impl/AntiSamyPolicyAdapter.java
@@ -21,7 +21,6 @@ package org.apache.sling.xss.impl;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -67,14 +66,23 @@ public class AntiSamyPolicyAdapter {
                 policyBuilder.allowAttributes(attribute.getName()).matching(cssValidator.newCssAttributePolicy())
                         .globally();
             } else {
-                List<String> allowedValuesFromAttribute = attribute.getLiterals();
-                for (String allowedValue : allowedValuesFromAttribute) {
-                    policyBuilder.allowAttributes(attribute.getName()).matching(true, allowedValue).globally();
-                }
+                List<String> literalList = attribute.getLiterals();
+                List<Pattern> patternList = attribute.getPatternList();
 
-                List<Pattern> regexsFromAttribute = attribute.getPatternList();
-                if (!regexsFromAttribute.isEmpty()) {
-                    policyBuilder.allowAttributes(attribute.getName()).matching(matchesToPatterns(regexsFromAttribute))
+                if (!literalList.isEmpty() && !patternList.isEmpty()) {
+                    // if both, the patterns and the literals are not empty, the value should be checked with them with an OR and not with an AND.
+                    policyBuilder.allowAttributes(attribute.getName())
+                        .matching(matchesPatternsOrLiterals(patternList, true, literalList))
+                        .globally();
+                }
+                else if (!literalList.isEmpty()) {
+                    policyBuilder.allowAttributes(attribute.getName())
+                        .matching(true, literalList.toArray(new String[0]))
+                        .globally();
+                }
+                else if (!patternList.isEmpty()) {
+                    policyBuilder.allowAttributes(attribute.getName())
+                            .matching(matchesToPatterns(patternList))
                             .globally();
                 } else {
                     policyBuilder.allowAttributes(attribute.getName()).globally();
@@ -172,16 +180,9 @@ public class AntiSamyPolicyAdapter {
                 }
 
                 List<Pattern> regexsFromAttribute = attribute.getPatternList();
-                for (Pattern regex : regexsFromAttribute) {
-                    dynamicAttributesPolicyMap.put(attribute.getName(), newDynamicAttributePolicy(regex));
-                }
-
                 List<String> allowedValuesFromAttribute = attribute.getLiterals();
-                if (!allowedValuesFromAttribute.isEmpty()) {
-                    dynamicAttributesPolicyMap.put(attribute.getName(),
-                            newDynamicAttributePolicy(true, allowedValuesFromAttribute.toArray(new String[0])));
-                }
 
+                dynamicAttributesPolicyMap.put(attribute.getName(), newDynamicAttributePolicy(regexsFromAttribute, true, allowedValuesFromAttribute));
             }
         }
 
@@ -222,43 +223,28 @@ public class AntiSamyPolicyAdapter {
     private static Predicate<String> matchesPatternsOrLiterals(List<Pattern> patternList, boolean ignoreCase, List<String> literalList) {
         return new Predicate<String>() {
             public boolean apply(String s) {
-                // check if the string matches to the pattern
-                for (Pattern pattern : patternList) {
-                    if (pattern.matcher(s).matches()) {
-                        return true;
-                    }
-                }
-                // if the pattern does not match it goes through the literals
-                for (String string : literalList) {
-                    s = ignoreCase
-                        ? s.toLowerCase()
-                        : s;
-                    if (string.equals(s)) {
-                        return true;
-                    }
-                }
-                // if it neither matches the patterns nor the literals it returns false
-                return false;
+                // check if the string matches to the pattern or one of the literal
+                s = ignoreCase ? s.toLowerCase() : s;
+                return matchesToPatterns(patternList).apply(s) || literalList.contains(s);
             }
         };
     }
 
-    public AttributePolicy newDynamicAttributePolicy(final Pattern pattern) {
+    public AttributePolicy newDynamicAttributePolicy(final List<Pattern> patternList, final boolean ignoreCase, final List<String> literalList) {
         return new AttributePolicy() {
             @Override
             public @Nullable String apply(String elementName, String attributeName, String value) {
-                return pattern.matcher(value).matches() ? value : null;
-            }
-        };
-    }
+                if (!literalList.isEmpty() && !patternList.isEmpty()) {
+                    return matchesPatternsOrLiterals(patternList, ignoreCase, literalList).apply(value) ? value : null;
 
-    public AttributePolicy newDynamicAttributePolicy(boolean ignoreCase, String... allowedValues) {
-        final List<String> allowed = Arrays.asList(allowedValues);
-        return new AttributePolicy() {
-            @Override
-            public @Nullable String apply(String elementName, String attributeName, String uncanonValue) {
-                String value = ignoreCase ? uncanonValue.toLowerCase() : uncanonValue;
-                return allowed.contains(value) ? value : null;
+                } else if (!literalList.isEmpty()) {
+                    value = ignoreCase ? value.toLowerCase() : value;
+                    return literalList.contains(value) ? value : null;
+
+                } else if (!patternList.isEmpty()) {
+                    return matchesToPatterns(patternList).apply(value) ? value : null;
+                }
+                return null;
             }
         };
     }
diff --git a/src/main/java/org/apache/sling/xss/impl/XSSFilterImpl.java b/src/main/java/org/apache/sling/xss/impl/XSSFilterImpl.java
index ade0fe8..86d9880 100644
--- a/src/main/java/org/apache/sling/xss/impl/XSSFilterImpl.java
+++ b/src/main/java/org/apache/sling/xss/impl/XSSFilterImpl.java
@@ -356,14 +356,13 @@ public class XSSFilterImpl implements XSSFilter {
 
     private void setPolicyHandler(PolicyHandler policyHandler) {
         Tag linkTag = policyHandler.getPolicy().getTagRules().get("a");
-        Attribute hrefAttribute = (linkTag != null) ? linkTag.getAttributeByName("href") : null;
+        hrefAttribute = (linkTag != null) ? linkTag.getAttributeByName("href") : null;
         if (hrefAttribute == null) {
             // Fallback to default configuration
             hrefAttribute = DEFAULT_HREF_ATTRIBUTE;
         }
 
         this.policyHandler = policyHandler;
-        this.hrefAttribute = hrefAttribute;
     }
 
     private class PolicyChangeListener implements ResourceChangeListener, ExternalResourceChangeListener {
diff --git a/src/main/java/org/apache/sling/xss/impl/xml/AntiSamyRules.java b/src/main/java/org/apache/sling/xss/impl/xml/AntiSamyRules.java
index 3e830a7..3c2c90e 100644
--- a/src/main/java/org/apache/sling/xss/impl/xml/AntiSamyRules.java
+++ b/src/main/java/org/apache/sling/xss/impl/xml/AntiSamyRules.java
@@ -20,6 +20,7 @@ package org.apache.sling.xss.impl.xml;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -124,4 +125,12 @@ public class AntiSamyRules {
         return regexpList.stream()
                 .collect(Collectors.toMap(Regexp::getName, Regexp::getPattern));
     }
+    
+    /**
+     * Attribute, Property and Tag names use the English locale, which may differ from the original config
+     */
+    static class AntiSamyConfigLocale {
+        static final Locale REGION = Locale.ENGLISH;
+    }
 }
+
diff --git a/src/main/java/org/apache/sling/xss/impl/xml/Attribute.java b/src/main/java/org/apache/sling/xss/impl/xml/Attribute.java
index c1a14eb..b553bad 100644
--- a/src/main/java/org/apache/sling/xss/impl/xml/Attribute.java
+++ b/src/main/java/org/apache/sling/xss/impl/xml/Attribute.java
@@ -25,6 +25,7 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 import org.apache.sling.xss.impl.AntiSamyActions;
+import org.apache.sling.xss.impl.xml.AntiSamyRules.AntiSamyConfigLocale;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@@ -46,7 +47,7 @@ public class Attribute {
             @JacksonXmlProperty(localName = "literal-list") List<Literal> literalList,
             @JacksonXmlProperty(localName = "onInvalid", isAttribute = true) String onInvalid,
             @JacksonXmlProperty(localName = "description", isAttribute = true) String description) {
-        this.name = name;
+        this.name = name.toLowerCase(AntiSamyConfigLocale.REGION);
         this.description = Optional.ofNullable(description).orElse("");
         this.onInvalid = onInvalid != null && onInvalid.length() > 0 ? onInvalid : AntiSamyActions.REMOVE_ATTRIBUTE_ON_INVALID;
         this.regexpList = Optional.ofNullable(allowedRegexps)
diff --git a/src/main/java/org/apache/sling/xss/impl/xml/MapBuilder.java b/src/main/java/org/apache/sling/xss/impl/xml/MapBuilder.java
index 734c363..0efbc8c 100644
--- a/src/main/java/org/apache/sling/xss/impl/xml/MapBuilder.java
+++ b/src/main/java/org/apache/sling/xss/impl/xml/MapBuilder.java
@@ -96,7 +96,7 @@ class MapBuilder {
             List<Regexp> allowedRegexps = getAllowedRegexps(attribute.getRegexpList());
             Attribute newAttribute = new Attribute(attribute.getName(), allowedRegexps, attribute.getLiteralList(),
                     attribute.getOnInvalid(), attribute.getDescription());
-            policy.commonAttributes.put(attribute.getName().toLowerCase(), newAttribute);
+            policy.commonAttributes.put(attribute.getName(), newAttribute);
         }
     }
 
@@ -126,10 +126,10 @@ class MapBuilder {
     private void parseGlobalAttributes(List<Attribute> root) throws InvalidConfigException {
         for (Attribute ele : root) {
             String name = ele.getName();
-            Attribute toAdd = policy.commonAttributes.get(name.toLowerCase());
+            Attribute toAdd = policy.commonAttributes.get(name);
 
             if (toAdd != null)
-                policy.globalAttributes.put(name.toLowerCase(), toAdd);
+                policy.globalAttributes.put(name, toAdd);
             else
                 throw new InvalidConfigException("Global attribute '" + name
                         + "' was not defined in <common-attributes>");
@@ -150,10 +150,10 @@ class MapBuilder {
     private void parseDynamicAttributes(List<Attribute> root) throws InvalidConfigException {
         for (Attribute ele : root) {
             String name = ele.getName();
-            Attribute toAdd = policy.getCommonAttributes().get(name.toLowerCase());
+            Attribute toAdd = policy.getCommonAttributes().get(name);
 
             if (toAdd != null) {
-                String attrName = name.toLowerCase().substring(0, name.length() - 1);
+                String attrName = name.substring(0, name.length() - 1);
                 policy.getDynamicAttributes().put(attrName, toAdd);
             } else
                 throw new InvalidConfigException("Dynamic attribute '" + name
@@ -173,7 +173,7 @@ class MapBuilder {
             List<Attribute> tagAttributes = getTagAttributes(attributeList, name);
             Tag tag = new Tag(name, action, tagAttributes);
 
-            policy.tagRules.put(name.toLowerCase(), tag);
+            policy.tagRules.put(name, tag);
         }
     }
 
@@ -183,7 +183,7 @@ class MapBuilder {
 
         for (Attribute attribute : attributeList) {
             Attribute newAttribute;
-            String attributeName = attribute.getName().toLowerCase();
+            String attributeName = attribute.getName();
             List<Regexp> regexps = attribute.getRegexpList();
             List<Literal> literals = attribute.getLiteralList();
             String onInvalid = attribute.getOnInvalid();
@@ -224,7 +224,7 @@ class MapBuilder {
             Property propertyWithPatterns = new Property(property.getName(), allowedRegexp3, property.getLiteralList(),
                     property.getShorthandList(), property.getDescription(), property.getOnInvalid(),
                     property.getDefaultValue());
-            policy.getCssRules().put(property.getName().toLowerCase(), propertyWithPatterns);
+            policy.getCssRules().put(property.getName(), propertyWithPatterns);
         }
     }
 
diff --git a/src/main/java/org/apache/sling/xss/impl/xml/Property.java b/src/main/java/org/apache/sling/xss/impl/xml/Property.java
index 94accb4..cdf8f9e 100644
--- a/src/main/java/org/apache/sling/xss/impl/xml/Property.java
+++ b/src/main/java/org/apache/sling/xss/impl/xml/Property.java
@@ -25,6 +25,7 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 import org.apache.sling.xss.impl.AntiSamyActions;
+import org.apache.sling.xss.impl.xml.AntiSamyRules.AntiSamyConfigLocale;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
@@ -58,7 +59,7 @@ public class Property {
             @JacksonXmlProperty(localName = "onInvalid", isAttribute = true) String onInvalidStr,
             @JacksonXmlProperty(isAttribute = true, localName = "default") String defaultValue) {
 
-        this.name = name;
+        this.name = name.toLowerCase(AntiSamyConfigLocale.REGION);
         this.description = Optional.ofNullable(description).orElse("");
         this.onInvalid = onInvalid != null && onInvalid.length() > 0 ? onInvalid : AntiSamyActions.REMOVE_ATTRIBUTE_ON_INVALID;
         this.regexpList = Optional.ofNullable(allowedRegexps)
diff --git a/src/main/java/org/apache/sling/xss/impl/xml/Tag.java b/src/main/java/org/apache/sling/xss/impl/xml/Tag.java
index a3e015f..c76b854 100644
--- a/src/main/java/org/apache/sling/xss/impl/xml/Tag.java
+++ b/src/main/java/org/apache/sling/xss/impl/xml/Tag.java
@@ -25,6 +25,8 @@ import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import org.apache.sling.xss.impl.xml.AntiSamyRules.AntiSamyConfigLocale;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
@@ -39,11 +41,11 @@ public class Tag {
             @JacksonXmlProperty(isAttribute = true, localName = "name") String name,
             @JacksonXmlProperty(isAttribute = true, localName = "action") String action,
             @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "attribute") List<Attribute> attributeList) {
-        this.name = name.toLowerCase();
+        this.name = name.toLowerCase(AntiSamyConfigLocale.REGION);
         this.attributeList = Optional.ofNullable(attributeList)
                 .map(Collections::unmodifiableList)
                 .orElseGet(Collections::emptyList);
-        this.action = action.toLowerCase();
+        this.action = action.toLowerCase(AntiSamyConfigLocale.REGION);
 
     }
 
diff --git a/src/test/java/org/apache/sling/xss/impl/AntiSamyPolicyTest.java b/src/test/java/org/apache/sling/xss/impl/AntiSamyPolicyTest.java
index 7b4d2d3..6626417 100644
--- a/src/test/java/org/apache/sling/xss/impl/AntiSamyPolicyTest.java
+++ b/src/test/java/org/apache/sling/xss/impl/AntiSamyPolicyTest.java
@@ -18,7 +18,6 @@
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.xss.impl;
 
-import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import javax.xml.stream.XMLStreamException;
@@ -52,19 +51,19 @@ public class AntiSamyPolicyTest {
     @ParameterizedTest
     @MethodSource("dataForScriptFiltering")
     public void testScriptFiltering(TestInput testInput) throws Exception {
-         testInput.runCheck();
+         testInput.runCheck(antiSamy);
     }
 
     @ParameterizedTest
     @MethodSource("dataForEventHandlerAttributes")
     public void testEventHandlerAttributes(TestInput testInput) throws Exception {
-       testInput.runCheck();
+       testInput.runCheck(antiSamy);
     }
 
     @ParameterizedTest
     @MethodSource("dataForImageFiltering")
     public void testImageFiltering(TestInput testInput) throws Exception {
-         testInput.runCheck();
+         testInput.runCheck(antiSamy);
     }
 
     @ParameterizedTest
@@ -80,20 +79,20 @@ public class AntiSamyPolicyTest {
     @ParameterizedTest
     @MethodSource("dataForURIFiltering")
     public void testURIFiltering(TestInput testInput) throws Exception {
-         testInput.runCheck();
+         testInput.runCheck(antiSamy);
     }
 
     @ParameterizedTest
     @MethodSource("dataForCSSFiltering")
     public void testCSSFiltering(TestInput testInput) throws Exception {
-         testInput.runCheck();
+         testInput.runCheck(antiSamy);
     }
 
     @ParameterizedTest
     @MethodSource("dataForDataAttributes")
     public void testDataAttributes(TestInput testInput) throws Exception {
          testInput.skipComparingInputWithOutput = false;
-         testInput.runCheck();
+         testInput.runCheck(antiSamy);
     }
 
     /**
@@ -102,7 +101,7 @@ public class AntiSamyPolicyTest {
     @ParameterizedTest
     @MethodSource("dataForIssueSLING8771")
     public void testIssueSLING8771(TestInput testInput) throws Exception {
-         testInput.runCheck();
+         testInput.runCheck(antiSamy);
         }
 
     private void testOutputIsEmpty(String input) throws Exception {
@@ -239,75 +238,4 @@ public class AntiSamyPolicyTest {
                         "<figcaption", true),
         };
     }
-
-    private static class TestInput {
-        String input;
-        String expectedPartialOutput;
-        boolean containsExpectedPartialOutput;
-        boolean skipComparingInputWithOutput;
-        Pattern pattern;
-
-
-        public TestInput(String input, String expectedPartialOutput, boolean containsExpectedPartialOutput) {
-            this(input, expectedPartialOutput, containsExpectedPartialOutput, false);
-        }
-
-        public TestInput(String input, String expectedPartialOutput, boolean containsExpectedPartialOutput, boolean skipComparingInputWithOutput) {
-            this.input = input;
-            this.expectedPartialOutput = expectedPartialOutput;
-            this.containsExpectedPartialOutput = containsExpectedPartialOutput;
-            this.skipComparingInputWithOutput = skipComparingInputWithOutput;
-        }
- 
-         public TestInput(String input, Pattern expectedPartialPattern, boolean containsExpectedPartialOutput, boolean skipComparingInputWithOutput) {
-             this.input = input;
-             this.pattern = expectedPartialPattern;
-             this.containsExpectedPartialOutput = containsExpectedPartialOutput;
-             this.skipComparingInputWithOutput = skipComparingInputWithOutput;
-         }
- 
-         void runCheck() throws Exception {
-               String cleanHTML = antiSamy.scan(input).getSanitizedString();
-               if (!skipComparingInputWithOutput) {
-                       if (pattern != null) {
-                               assertTrue(pattern.matcher(input.toLowerCase()).find(), String.format(
-                                               "Test is not properly configured: input '%s' doesn't seem to partialy matcht to following pattern:'%s' (case-insensitive match).",
-                                               input, expectedPartialOutput.toString()));
-                       } else {
-                               assertTrue(input.toLowerCase().contains(expectedPartialOutput.toLowerCase()), String.format(
-                                               "Test is not properly configured: input '%s' doesn't seem to contain '%s' (case-insensitive match).",
-                                               input, expectedPartialOutput));
-                       }
-               }
-               if (containsExpectedPartialOutput) {
-                       if (pattern != null) {
-                               assertTrue(
-                                               pattern.matcher(antiSamy.scan(input).getSanitizedString()).find(),
-                                               String.format("Expected that filtered output '%s' for input '%s' would partialy match to following pattern: '%s'.",
-                                                               cleanHTML,
-                                                               input,
-                                                               expectedPartialOutput));
-                       } else {
-                               assertTrue(
-                                               antiSamy.scan(input).getSanitizedString().contains(expectedPartialOutput),
-                                               String.format("Expected that filtered output '%s' for input '%s' would contain '%s'.",
-                                                               cleanHTML,
-                                                               input,
-                                                               expectedPartialOutput));
-                       }
-               } else {
-                       if (pattern != null) {
-                               assertFalse(pattern.matcher(antiSamy.scan(input).getSanitizedString()).find(),
-                                               String.format("Expected that filtered output '%s' for input '%s', would NOT partialy match to following pattern:: '%s'.",
-                                                               cleanHTML,
-                                                               input, expectedPartialOutput));
-                       } else {
-                               assertFalse(antiSamy.scan(input).getSanitizedString().contains(expectedPartialOutput),
-                                               String.format("Expected that filtered output '%s' for input '%s', would NOT contain '%s'.",
-                                                               cleanHTML,
-                                                               input, expectedPartialOutput));
-                       }
-               }
-       }
-    }
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/xss/impl/AntiSamyPolicyWithAdditionalGlobalAndDynamicConditionsTest.java b/src/test/java/org/apache/sling/xss/impl/AntiSamyPolicyWithAdditionalGlobalAndDynamicConditionsTest.java
new file mode 100644
index 0000000..39aced6
--- /dev/null
+++ b/src/test/java/org/apache/sling/xss/impl/AntiSamyPolicyWithAdditionalGlobalAndDynamicConditionsTest.java
@@ -0,0 +1,78 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements.  See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership.  The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License.  You may obtain a copy of the License at
+ ~
+ ~   http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied.  See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.xss.impl;
+
+import javax.xml.stream.XMLStreamException;
+
+import java.io.IOException;
+
+import org.apache.sling.xss.impl.xml.AntiSamyPolicy;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public class AntiSamyPolicyWithAdditionalGlobalAndDynamicConditionsTest {
+
+    public static final String POLICY_FILE = "./configWithAdditionalGlobalAndDynamicConditions.xml";
+    private static HtmlSanitizer antiSamy;
+
+    @BeforeAll
+    public static void setup() throws InvalidConfigException, XMLStreamException, IOException {
+        antiSamy = new HtmlSanitizer(new AntiSamyPolicy(AntiSamyPolicyWithAdditionalGlobalAndDynamicConditionsTest.class.getClassLoader().getResourceAsStream(POLICY_FILE)));
+    }
+
+    @ParameterizedTest
+    @MethodSource("dataForDynamicAttributes")
+    public void testDynamicAttributes(TestInput testInput) throws Exception {
+         testInput.skipComparingInputWithOutput = false;
+         testInput.runCheck(antiSamy);
+    }
+
+    @ParameterizedTest
+    @MethodSource("dataForGlobalAttributes")
+    public void testGlobalAttributes(TestInput testInput) throws Exception {
+         testInput.skipComparingInputWithOutput = false;
+         testInput.runCheck(antiSamy);
+    }
+
+
+    static TestInput[] dataForGlobalAttributes() {
+        return new TestInput[]{
+                new TestInput("<p draggable=\"wrong\">This is a paragraph.</p>",
+                        "<p",false),
+                new TestInput("<p draggable=\"auto\">This is a paragraph.</p>",
+                        "<p", true),
+                new TestInput("<p draggable=\"true\">This is a draggable paragraph.</p>",
+                        "<p", true),
+                new TestInput("<p contenteditable=\"wrong\">This is a paragraph.</p>",
+                        "<p",false),
+                new TestInput("<p contenteditable=\"true\">This is a paragraph.</p>",
+                        "<p", true),
+        };
+    }
+
+     static TestInput[] dataForDynamicAttributes() {
+        return new TestInput[]{
+                new TestInput("<p data-test=\"test-purpose\">This is a paragraph.</p>",
+                       "<p data-test=\"test-purpose\">This is a paragraph.</p>", true),
+                new TestInput("<p data-test=\"test\">This is a paragraph.</p>",
+                       "<p data-test=\"test\">This is a paragraph.</p>", true),
+                };
+        }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/xss/impl/TestInput.java b/src/test/java/org/apache/sling/xss/impl/TestInput.java
new file mode 100644
index 0000000..817d3be
--- /dev/null
+++ b/src/test/java/org/apache/sling/xss/impl/TestInput.java
@@ -0,0 +1,95 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements.  See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership.  The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License.  You may obtain a copy of the License at
+ ~
+ ~   http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied.  See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.xss.impl;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.regex.Pattern;
+
+public class TestInput {
+    String input;
+    String expectedPartialOutput;
+    boolean containsExpectedPartialOutput;
+    boolean skipComparingInputWithOutput;
+    Pattern pattern;
+
+
+    public TestInput(String input, String expectedPartialOutput, boolean containsExpectedPartialOutput) {
+        this(input, expectedPartialOutput, containsExpectedPartialOutput, false);
+    }
+
+    public TestInput(String input, String expectedPartialOutput, boolean containsExpectedPartialOutput, boolean skipComparingInputWithOutput) {
+        this.input = input;
+        this.expectedPartialOutput = expectedPartialOutput;
+        this.containsExpectedPartialOutput = containsExpectedPartialOutput;
+        this.skipComparingInputWithOutput = skipComparingInputWithOutput;
+    }
+
+    public TestInput(String input, Pattern expectedPartialPattern, boolean containsExpectedPartialOutput, boolean skipComparingInputWithOutput) {
+        this.input = input;
+        this.pattern = expectedPartialPattern;
+        this.containsExpectedPartialOutput = containsExpectedPartialOutput;
+        this.skipComparingInputWithOutput = skipComparingInputWithOutput;
+    }
+
+    void runCheck(HtmlSanitizer antiSamy) throws Exception {
+        String cleanHTML = antiSamy.scan(input).getSanitizedString();
+        if (!skipComparingInputWithOutput) {
+                if (pattern != null) {
+                        assertTrue(pattern.matcher(input.toLowerCase()).find(), String.format(
+                                        "Test is not properly configured: input '%s' doesn't seem to partialy matcht to following pattern:'%s' (case-insensitive match).",
+                                        input, expectedPartialOutput.toString()));
+                } else {
+                        assertTrue(input.toLowerCase().contains(expectedPartialOutput.toLowerCase()), String.format(
+                                        "Test is not properly configured: input '%s' doesn't seem to contain '%s' (case-insensitive match).",
+                                        input, expectedPartialOutput));
+                }
+        }
+        if (containsExpectedPartialOutput) {
+                if (pattern != null) {
+                        assertTrue(
+                                        pattern.matcher(antiSamy.scan(input).getSanitizedString()).find(),
+                                        String.format("Expected that filtered output '%s' for input '%s' would partialy match to following pattern: '%s'.",
+                                                        cleanHTML,
+                                                        input,
+                                                        expectedPartialOutput));
+                } else {
+                        assertTrue(
+                                        antiSamy.scan(input).getSanitizedString().contains(expectedPartialOutput),
+                                        String.format("Expected that filtered output '%s' for input '%s' would contain '%s'.",
+                                                        cleanHTML,
+                                                        input,
+                                                        expectedPartialOutput));
+                }
+        } else {
+                if (pattern != null) {
+                        assertFalse(pattern.matcher(antiSamy.scan(input).getSanitizedString()).find(),
+                                        String.format("Expected that filtered output '%s' for input '%s', would NOT partialy match to following pattern:: '%s'.",
+                                                        cleanHTML,
+                                                        input, expectedPartialOutput));
+                } else {
+                        assertFalse(antiSamy.scan(input).getSanitizedString().contains(expectedPartialOutput),
+                                        String.format("Expected that filtered output '%s' for input '%s', would NOT contain '%s'.",
+                                                        cleanHTML,
+                                                        input, expectedPartialOutput));
+                }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/configWithAdditionalGlobalAndDynamicConditions.xml b/src/test/resources/configWithAdditionalGlobalAndDynamicConditions.xml
new file mode 100644
index 0000000..f810dbd
--- /dev/null
+++ b/src/test/resources/configWithAdditionalGlobalAndDynamicConditions.xml
@@ -0,0 +1,2860 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~ Licensed to the Apache Software Foundation (ASF) under one or
+  ~ more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information regarding
+  ~ copyright ownership. The ASF licenses this file to you under the
+  ~ Apache License, Version 2.0 (the "License"); you may not use
+  ~ this file except in compliance with the License. You may obtain
+  ~ a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0 Unless required by
+  ~ applicable law or agreed to in writing, software distributed
+  ~ under the License is distributed on an "AS IS" BASIS, WITHOUT
+  ~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions
+  ~ and limitations under the License.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<!--
+W3C rules retrieved from:
+http://www.w3.org/TR/html401/struct/global.html
+-->
+<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="antisamy.xsd">
+
+    <directives>
+        <directive name="omitXmlDeclaration" value="true"/>
+        <directive name="omitDoctypeDeclaration" value="true"/>
+        <directive name="maxInputSize" value="200000"/>
+        <directive name="useXHTML" value="true"/>
+        <directive name="formatOutput" value="false"/>
+        <directive name="nofollowAnchors" value="false"/>
+        <directive name="validateParamAsEmbed" value="true"/>
+        <directive name="preserveSpace" value="true"/>
+
+        <!--
+        remember, this won't work for relative URIs - AntiSamy doesn't
+        know anything about the URL or your web structure
+        -->
+        <directive name="embedStyleSheets" value="false"/>
+        <directive name="connectionTimeout" value="5000"/>
+        <directive name="maxStyleSheetImports" value="3"/>
+
+        <!-- Allows the use of dynamic attributes (i.e. HTML5 "data-") -->
+        <directive name="allowDynamicAttributes" value="true"/>
+    </directives>
+
+    <common-regexps>
+
+        <!--
+        From W3C:
+        This attribute assigns a class name or set of class names to an
+        element. Any number of elements may be assigned the same class
+        name or names. Multiple class names must be separated by white
+        space characters.
+        -->
+
+        <!-- The 16 colors defined by the HTML Spec (also used by the CSS Spec) -->
+        <regexp name="colorName"
+                value="(aqua|black|blue|fuchsia|gray|grey|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow)"/>
+
+        <!-- HTML/CSS Spec allows 3 or 6 digit hex to specify color -->
+        <regexp name="colorCode" value="(#([0-9a-fA-F]{6}|[0-9a-fA-F]{3}))"/>
+
+        <regexp name="anything" value=".*"/>
+        <regexp name="numberOrPercent" value="(\d)+(%{0,1})"/>
+        <regexp name="paragraph" value="([\p{L}\p{N},'\.\s\-_\(\)\?]|&amp;[0-9]{2};)*"/>
+        <regexp name="htmlId" value="[a-zA-Z0-9\:\-_\.]+"/>
+        <regexp name="htmlTitle" value="[\p{L}\p{N}\s\-_',:\[\]!\./\\\(\)&amp;]*"/>
+        <!-- force non-empty with a '+' at the end instead of '*' -->
+        <regexp name="htmlClass" value="[a-zA-Z0-9\s,\-_]+"/>
+
+        <!-- Allow empty URL attributes with a '*'-quantifier instead of '+' for the first part of the regexp -->
+        <!-- Check org.apache.sling.xss.impl.XSSFilterImpl#RELATIVE_REF to understand the regexp -->
+        <regexp name="onsiteURL"
+            value="(?!\s*javascript(?::|&amp;colon;))(?:(?://(?:(?:(?:(?:\p{L}\p{M}*)|[\p{N}-._~])|(?:%\p{XDigit}\p{XDigit})|(?:[!$&amp;&apos;()*+,;=]))*@)?(?:\[(?:(?:(?:\p{XDigit}{1,4}:){6}(?:(?:\p{XDigit}{1,4}:\p{XDigit}{1,4})|(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N} [...]
+        <!-- Check org.apache.sling.xss.impl.XSSFilterImpl#URI to understand the regexp -->
+        <regexp name="offsiteURL"
+                value="(?!\s*javascript)\p{L}[\p{L}\p{N}+.\-]*:(?:(?://(?:(?:(?:(?:\p{L}\p{M}*)|[\p{N}-._~])|(?:%\p{XDigit}\p{XDigit})|(?:[!$&amp;&apos;()*+,;=]))*@)?(?:\[(?:(?:(?:\p{XDigit}{1,4}:){6}(?:(?:\p{XDigit}{1,4}:\p{XDigit}{1,4})|(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30- [...]
+
+        <regexp name="boolean" value="(true|false)"/>
+        <regexp name="singlePrintable" value="[a-zA-Z0-9]{1}"/>
+        <!-- \w allows the '_' character -->
+
+        <!-- This is for elements (ex: elemName { ... }) -->
+        <regexp name="cssElementSelector" value="[a-zA-Z0-9\-_]+|\*"/>
+
+        <!--  This is to list out any element names that are *not* valid -->
+        <regexp name="cssElementExclusion" value=""/>
+
+        <!--  This if for classes (ex: .className { ... }) -->
+        <regexp name="cssClassSelector" value="\.[a-zA-Z0-9\-_]+"/>
+
+        <!--  This is to list out any class names that are *not* valid -->
+        <regexp name="cssClassExclusion" value=""/>
+
+        <!--  This is for ID selectors (ex: #myId { ... } -->
+        <regexp name="cssIDSelector" value="#[a-zA-Z0-9\-_]+"/>
+
+        <!--  This is to list out any IDs that are *not* valid - FIXME: What should the default be to avoid div hijacking? *? -->
+        <regexp name="cssIDExclusion" value=""/>
+
+        <!--  This is for pseudo-element selector (ex. foo:pseudo-element { ... } -->
+        <regexp name="cssPseudoElementSelector" value=":[a-zA-Z0-9\-_]+"/>
+
+        <!--  This is to list out any psuedo-element names that are *not* valid -->
+        <regexp name="cssPsuedoElementExclusion" value=""/>
+
+        <!--  This is for attribute selectors (ex. foo[attr=value] { ... } -->
+        <regexp name="cssAttributeSelector" value="\[[a-zA-Z0-9\-_]+((=|~=|\|=){1}[a-zA-Z0-9\-_]+){1}\]"/>
+
+        <!--  This is to list out any attribute names that are *not* valid -->
+        <regexp name="cssAttributeExclusion" value=""/>
+
+        <!--  This is for resources referenced from CSS (such as background images and other imported stylesheets) -->
+        <regexp name="cssOnsiteUri" value="url\((?!\s*javascript(?::|&amp;colon;))(?:(?://(?:(?:(?:(?:\p{L}\p{M}*)|[\p{N}-._~])|(?:%\p{XDigit}\p{XDigit})|(?:[!$&amp;&apos;()*+,;=]))*@)?(?:\[(?:(?:(?:\p{XDigit}{1,4}:){6}(?:(?:\p{XDigit}{1,4}:\p{XDigit}{1,4})|(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N [...]
+        <regexp name="cssOffsiteUri" value="url\((?!\s*javascript)\p{L}[\p{L}\p{N}+.\-]*:(?:(?://(?:(?:(?:(?:\p{L}\p{M}*)|[\p{N}-._~])|(?:%\p{XDigit}\p{XDigit})|(?:[!$&amp;&apos;()*+,;=]))*@)?(?:\[(?:(?:(?:\p{XDigit}{1,4}:){6}(?:(?:\p{XDigit}{1,4}:\p{XDigit}{1,4})|(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x39]\p{N}|1\p{N}{2}|2[\x30-\x34]\p{N}|25[\x30-\x35])\.(?:\p{N}|[\x31-\x [...]
+
+        <!--  This if for CSS Identifiers -->
+        <regexp name="cssIdentifier" value="[a-zA-Z0-9\-_]+"/>
+
+        <!--  This is for comments within CSS (ex. /* comment */) -->
+        <regexp name="cssCommentText" value="[\p{L}\p{N}\-_,\/\\\.\s\(\)!\?\=\$#%\^&amp;:&quot;']+"/>
+
+        <regexp name="integer" value="(-|\+)?[0-9]+"/>
+        <regexp name="positiveInteger" value="(\+)?[0-9]+"/>
+        <regexp name="number" value="(-|\+)?([0-9]+(\.[0-9]+)?)"/>
+        <regexp name="angle" value="(-|\+)?([0-9]+(\.[0-9]+)?)(deg|grads|rad)"/>
+        <regexp name="time" value="([0-9]+(\.[0-9]+)?)(ms|s)"/>
+        <regexp name="frequency" value="([0-9]+(\.[0-9]+)?)(hz|khz)"/>
+        <regexp name="length" value="((-|\+)?0|(-|\+)?([0-9]+(\.[0-9]+)?)(em|ex|px|in|cm|mm|pt|pc))"/>
+        <regexp name="positiveLength" value="((\+)?0|(\+)?([0-9]+(\.[0-9]+)?)(em|ex|px|in|cm|mm|pt|pc))"/>
+        <regexp name="percentage" value="(-|\+)?([0-9]+(\.[0-9]+)?)%"/>
+        <regexp name="positivePercentage" value="(\+)?([0-9]+(\.[0-9]+)?)%"/>
+
+        <regexp name="absolute-size" value="(xx-small|x-small|small|medium|large|x-large|xx-large)"/>
+        <regexp name="relative-size" value="(larger|smaller)"/>
+
+        <!-- Used for CSS Color specifications (complex regexp expresses integer values of 0-255) -->
+        <regexp name="rgbCode"
+                value="rgb\(([1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]),([1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]),([1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\)"/>
+
+        <!-- CSS2 Allowed System Color Values -->
+        <regexp name="systemColor"
+                value="(activeborder|activecaption|appworkspace|background|buttonface|buttonhighlight|buttonshadow|buttontext|captiontext|graytext|highlight|highlighttext|inactiveborder|inactivecaption|inactivecaptiontext|infobackground|infotext|menu|menutext|scrollbar|threeddarkshadow|threedface|threedhighlight|threedlightshadow|threedshadow|window|windowframe|windowtext)"/>
+
+        <!-- This is where we specify what Flash src to allow -->
+        <regexp name="flashSites"
+                value="http://(download\.macromedia\.com/pub|www\.macromedia\.com/(go|shockwave)|c\.brightcove\.com/services|gamevideos\.1up\.com/swf|www\.youtube\.com/v|vimeo\.com|www\.gametrailers\.com|videomedia\.ign\.com/ev|image\.com\.com/gamespot|www\.hulu\.com/embed|embed\.break\.com|player\.ordienetworks\.com/flash|www\.adultswim\.com/video/vplayer|www\.dailymotion\.com/swf|www\.ustream\.tv/flash/video|cdn-i\.dmdentertainment\.com|media\.mtvnservices\.com|www\.justin\.tv/widgets| [...]
+    </common-regexps>
+
+    <!--
+
+    Tag.name = a, b, div, body, etc.
+    Tag.action = filter: remove tags, but keep content, validate: keep content as long as it passes rules, remove: remove tag and contents
+    Attribute.name = id, class, href, align, width, etc.
+    Attribute.onInvalid = what to do when the attribute is invalid, e.g., remove the tag (removeTag), remove the attribute (removeAttribute), filter the tag (filterTag)
+    Attribute.description = What rules in English you want to tell the users they can have for this attribute. Include helpful things so they'll be able to tune their HTML
+
+     -->
+
+    <!--
+    Some attributes are common to all (or most) HTML tags. There aren't many that qualify for this. You have to make sure there's no
+    collisions between any of these attribute names with attribute names of other tags that are for different purposes.
+    -->
+
+    <common-attributes>
+        <!-- this attributes are only created for testing purposes -->
+        <attribute name="draggable" onInvalid="removeTag">
+            <regexp-list>
+                <regexp name="boolean"/>
+            </regexp-list>
+            <literal-list>
+                <literal value="auto"/>
+            </literal-list>
+        </attribute>
+        <attribute name="contenteditable" onInvalid="removeTag">
+            <literal-list>
+                <literal value="true"/>
+                <literal value="false"/>
+            </literal-list>
+        </attribute>
+
+        <!-- Common to all HTML tags  -->
+
+        <attribute name="target">
+            <regexp-list>
+                <regexp value="[a-zA-Z0-9-_\$]+"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="id" description="The 'id' of any HTML attribute should not contain anything besides letters and numbers">
+            <regexp-list>
+                <regexp name="htmlId"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="classid">
+            <regexp-list>
+                <regexp name="anything"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="codebase">
+            <regexp-list>
+                <regexp name="flashSites"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="class"
+                   description="The 'class' of any HTML attribute is usually a single word, but it can also be a list of class names separated by spaces">
+            <regexp-list>
+                <regexp name="htmlClass"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="lang"
+                   description="The 'lang' attribute tells the browser what language the element's attribute values and content are written in">
+            <regexp-list>
+                <regexp value="[a-zA-Z]{2,20}"/>
+            </regexp-list>
+        </attribute>
+        <attribute name="title"
+                   description="The 'title' attribute provides text that shows up in a 'tooltip' when a user hovers their mouse over the element">
+            <regexp-list>
+                <regexp name="htmlTitle"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="alt"
+                   description="The 'alt' attribute provides alternative text to users when its visual representation is not available">
+            <regexp-list>
+                <regexp name="paragraph"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="data-" description="Allows the HTML5 'data-' attribute to be added to elements">
+            <regexp-list>
+                <regexp name="anything"/>
+            </regexp-list>
+            <literal-list>
+                <literal value="test-purpose"/>
+            </literal-list>
+
+        </attribute>
+
+
+        <!-- the "style" attribute will be validated by an inline stylesheet scanner, so no need to define anything here - i hate having to special case this but no other choice -->
+        <attribute name="style"
+                   description="The 'style' attribute provides the ability for users to change many attributes of the tag's contents using a strict syntax"/>
+
+        <attribute name="media">
+            <regexp-list>
+                <regexp value="[a-zA-Z0-9,\-\s]+"/>
+            </regexp-list>
+
+            <literal-list>
+                <literal value="screen"/>
+                <literal value="tty"/>
+                <literal value="tv"/>
+                <literal value="projection"/>
+                <literal value="handheld"/>
+                <literal value="print"/>
+                <literal value="braille"/>
+                <literal value="aural"/>
+                <literal value="all"/>
+            </literal-list>
+
+        </attribute>
+
+
+        <!-- Anchor related -->
+
+        <!--  onInvalid="filterTag" has been removed as per suggestion at OWASP SJ 2007 - just "name" is valid -->
+        <attribute name="href">
+            <regexp-list>
+                <regexp name="onsiteURL"/>
+                <regexp name="offsiteURL"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="name">
+            <regexp-list>
+
+                <regexp value="[a-zA-Z0-9-\_\$]+"/>
+
+                <!--
+                have to allow the $ for .NET controls - although,
+                will users be supplying input that has server-generated
+                .NET control names? methinks not, but i want to pass my
+                test cases
+                -->
+
+            </regexp-list>
+        </attribute>
+
+
+        <attribute name="shape" description="The 'shape' attribute defines the shape of the selectable area">
+            <literal-list>
+                <literal value="default"/>
+                <literal value="rect"/>
+                <literal value="circle"/>
+                <literal value="poly"/>
+            </literal-list>
+        </attribute>
+
+
+        <!--  Table attributes  -->
+
+        <attribute name="border">
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="cellpadding">
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="cellspacing">
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="colspan">
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="rowspan">
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="background">
+            <regexp-list>
+                <regexp name="onsiteURL"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="bgcolor">
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="abbr">
+            <regexp-list>
+                <regexp name="paragraph"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="headers" description="The 'headers' attribute is a space-separated list of cell IDs">
+            <regexp-list>
+                <regexp value="[a-zA-Z0-9\s*]*"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="charoff">
+            <regexp-list>
+                <regexp value="numberOrPercent"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="char">
+            <regexp-list>
+                <regexp value=".{0,1}"/>
+            </regexp-list>
+        </attribute>
+
+
+        <attribute name="axis" description="The 'headers' attribute is a comma-separated list of related header cells">
+            <regexp-list>
+                <regexp value="[a-zA-Z0-9\s*,]*"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="nowrap" description="The 'nowrap' attribute tells the browser not to wrap text that goes over one line">
+            <regexp-list>
+                <regexp name="anything"/>
+                <!-- <regexp value="(nowrap){0,1}"/>  -->
+            </regexp-list>
+        </attribute>
+
+
+        <!--  Common positioning attributes  -->
+
+        <attribute name="width">
+            <regexp-list>
+                <regexp name="numberOrPercent"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="height">
+            <regexp-list>
+                <regexp name="numberOrPercent"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="align"
+                   description="The 'align' attribute of an HTML element is a direction word, like 'left', 'right' or 'center'">
+            <literal-list>
+                <literal value="center"/>
+                <literal value="middle"/>
+                <literal value="left"/>
+                <literal value="right"/>
+                <literal value="justify"/>
+                <literal value="char"/>
+            </literal-list>
+        </attribute>
+
+        <attribute name="valign"
+                   description="The 'valign' attribute of an HTML attribute is a direction word, like 'baseline','bottom','middle' or 'top'">
+            <literal-list>
+                <literal value="baseline"/>
+                <literal value="bottom"/>
+                <literal value="middle"/>
+                <literal value="top"/>
+            </literal-list>
+        </attribute>
+
+
+        <!-- Intrinsic JavaScript Events -->
+
+        <attribute name="onFocus" description="The 'onFocus' event is executed when the control associated with the tag gains focus">
+            <literal-list>
+                <literal value="javascript:void(0)"/>
+                <literal value="javascript:history.go(-1)"/>
+            </literal-list>
+        </attribute>
+
+        <attribute name="onBlur" description="The 'onBlur' event is executed when the control associated with the tag loses focus">
+            <literal-list>
+                <literal value="javascript:void(0)"/>
+                <literal value="javascript:history.go(-1)"/>
+            </literal-list>
+        </attribute>
+
+        <attribute name="onClick" description="The 'onClick' event is executed when the control associated with the tag is clicked">
+            <literal-list>
+                <literal value="javascript:void(0)"/>
+                <literal value="javascript:history.go(-1)"/>
+            </literal-list>
+        </attribute>
+
+        <attribute name="onDblClick"
+                   description="The 'onDblClick' event is executed when the control associated with the tag is clicked twice immediately">
+            <literal-list>
+                <literal value="javascript:void(0)"/>
+                <literal value="javascript:history.go(-1)"/>
+            </literal-list>
+        </attribute>
+
+        <attribute name="onMouseDown"
+                   description="The 'onMouseDown' event is executed when the control associated with the tag is clicked but not yet released">
+            <literal-list>
+                <literal value="javascript:void(0)"/>
+                <literal value="javascript:history.go(-1)"/>
+            </literal-list>
+        </attribute>
+
+        <attribute name="onMouseUp"
+                   description="The 'onMouseUp' event is executed when the control associated with the tag is clicked after the button is released">
+            <literal-list>
+                <literal value="javascript:void(0)"/>
+                <literal value="javascript:history.go(-1)"/>
+            </literal-list>
+        </attribute>
+
+        <attribute name="onMouseOver"
+                   description="The 'onMouseOver' event is executed when the user's mouse hovers over the control associated with the tag">
+            <literal-list>
+                <literal value="javascript:void(0)"/>
+                <literal value="javascript:history.go(-1)"/>
+            </literal-list>
+        </attribute>
+
+        <attribute name="scope" description="The 'scope' attribute defines what's covered by the header cells">
+            <literal-list>
+                <literal value="row"/>
+                <literal value="col"/>
+                <literal value="rowgroup"/>
+                <literal value="colgroup"/>
+            </literal-list>
+        </attribute>
+
+
+        <!-- If you want users to be able to mess with tabindex, uncomment this -->
+        <!--
+        <attribute name="tabindex" description="...">
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </attribute>
+         -->
+
+
+        <!-- Input/form related common attributes -->
+
+        <attribute name="disabled">
+            <regexp-list>
+                <regexp name="anything"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="readonly">
+            <regexp-list>
+                <regexp name="anything"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="accesskey">
+            <regexp-list>
+                <regexp name="anything"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="size">
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </attribute>
+
+
+        <attribute name="autocomplete">
+            <literal-list>
+                <literal value="on"/>
+                <literal value="off"/>
+            </literal-list>
+        </attribute>
+
+        <attribute name="rows">
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </attribute>
+
+        <attribute name="cols">
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </attribute>
+
+    </common-attributes>
+
+
+    <!--
+    This requires normal updates as browsers continue to diverge from the W3C and each other. As long as the browser wars continue
+    this is going to continue. I'm not sure war is the right word for what's going on. Doesn't somebody have to win a war after
+    a while? Even wars of attrition, surely?
+     -->
+
+    <global-tag-attributes>
+        <!-- Not valid in base, head, html, meta, param, script, style, and title elements. -->
+        <attribute name="id"/>
+        <attribute name="style"/>
+        <attribute name="title"/>
+        <attribute name="class"/>
+        <!-- Not valid in base, br, frame, frameset, hr, iframe, param, and script elements.  -->
+        <attribute name="lang"/>
+
+        <attribute name="draggable"/>
+        <attribute name="contenteditable"/>
+    </global-tag-attributes>
+
+    <!-- Declare "dynamic" tag attributes here. The directive "allowDynamicAttributes" must be set to true -->
+    <dynamic-tag-attributes>
+        <attribute name="data-"/> <!-- HTML5 "data-" tag -->
+    </dynamic-tag-attributes>
+
+    <tags-to-encode>
+        <tag>g</tag>
+        <tag>grin</tag>
+    </tags-to-encode>
+
+    <tag-rules>
+
+        <!-- You can mess with this stuff if you know what you're doing -->
+
+        <tag name="html" action="validate"/>
+
+        <tag name="body" action="validate">
+            <attribute name="bgcolor"/>
+        </tag>
+
+        <tag name="meta" action="filter"/>
+
+        <tag name="head" action="validate"/>
+
+        <!-- since we're validating the style sheets this is safe to have - switch to "truncate" if the user's html will appear in the html body -->
+        <tag name="title" action="truncate"/>
+
+
+        <!-- Tags related to JavaScript -->
+
+        <tag name="script" action="remove"/>
+        <tag name="noscript" action="validate"/>
+        <!-- although no javascript can fire inside a noscript tag, css is still a viable attack vector -->
+
+
+        <!-- Frame & related tags -->
+
+        <tag name="iframe" action="remove"/>
+        <tag name="frameset" action="remove"/>
+        <tag name="frame" action="remove"/>
+
+
+        <!-- Form related tags -->
+
+        <tag name="label" action="validate">
+            <attribute name="for">
+                <regexp-list>
+                    <regexp name="htmlId"/>
+                </regexp-list>
+            </attribute>
+        </tag>
+
+
+        <!--
+            If you wish to enable any of the form related tags, change the tag's action below from "filter" or "remove" to "validate". The attributes have been
+            hardened so this is safe to do, if it's something you want to allow. Beware the <><ing possibilities!
+         -->
+
+        <tag name="form" action="validate">
+
+            <attribute name="action">
+                <regexp-list>
+                    <regexp name="onsiteURL"/>
+                    <regexp name="offsiteURL"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="name"/>
+
+            <attribute name="autocomplete"/>
+
+            <attribute name="method">
+                <literal-list>
+                    <literal value="post"/>
+                    <literal value="get"/>
+                </literal-list>
+            </attribute>
+
+        </tag>
+
+        <tag name="button" action="validate">
+            <attribute name="name"/>
+            <attribute name="value">
+                <regexp-list>
+                    <regexp name="anything"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="disabled"/>
+            <attribute name="accesskey"/>
+            <attribute name="type">
+                <literal-list>
+                    <literal value="submit"/>
+                    <literal value="reset"/>
+                    <literal value="button"/>
+                </literal-list>
+            </attribute>
+        </tag>
+
+        <tag name="input" action="validate">
+
+            <attribute name="name"/>
+
+            <attribute name="size"/>
+
+            <attribute name="maxlength">
+                <regexp-list>
+                    <regexp name="number"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="autocomplete"/>
+
+            <attribute name="checked">
+                <regexp-list>
+                    <regexp name="anything"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="alt"/>
+
+            <attribute name="src">
+                <regexp-list>
+                    <regexp name="onsiteURL"/>
+                    <regexp name="offsiteURL"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="usemap">
+                <regexp-list>
+                    <regexp name="onsiteURL"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="type">
+                <literal-list>
+                    <literal value="hidden"/>
+                    <literal value="text"/>
+                    <literal value="password"/>
+                    <literal value="radio"/>
+                    <literal value="checkbox"/>
+                    <literal value="submit"/>
+                    <literal value="button"/>
+                    <literal value="image"/>
+                    <literal value="file"/>
+                    <literal value="reset"/>
+                </literal-list>
+            </attribute>
+
+            <attribute name="value">
+                <regexp-list>
+                    <regexp name="anything"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="disabled"/>
+            <attribute name="readonly"/>
+            <attribute name="accesskey"/>
+
+            <attribute name="border"/>
+
+        </tag>
+
+        <tag name="select" action="validate">
+
+            <attribute name="name"/>
+            <attribute name="disabled"/>
+
+            <attribute name="multiple">
+                <regexp-list>
+                    <regexp name="anything"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="size"/>
+
+        </tag>
+
+        <tag name="option" action="validate">
+
+            <attribute name="disabled"/>
+
+            <attribute name="value">
+                <regexp-list>
+                    <regexp name="anything"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="label">
+                <regexp-list>
+                    <regexp name="anything"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="selected">
+                <regexp-list>
+                    <regexp name="anything"/>
+                </regexp-list>
+            </attribute>
+        </tag>
+
+        <tag name="textarea" action="validate">
+            <attribute name="rows"/>
+            <attribute name="cols"/>
+            <attribute name="name"/>
+            <attribute name="disabled"/>
+            <attribute name="readonly"/>
+            <attribute name="accesskey"/>
+        </tag>
+
+
+        <!-- All formatting tags -->
+
+        <tag name="h1" action="validate"/>
+        <tag name="h2" action="validate"/>
+        <tag name="h3" action="validate"/>
+        <tag name="h4" action="validate"/>
+        <tag name="h5" action="validate"/>
+        <tag name="h6" action="validate"/>
+
+        <tag name="p" action="validate">
+            <attribute name="align"/>
+        </tag>
+
+        <tag name="i" action="validate"/>
+        <tag name="b" action="validate"/>
+        <tag name="u" action="validate"/>
+        <tag name="strong" action="validate"/>
+
+        <tag name="em" action="validate"/>
+        <tag name="small" action="validate"/>
+        <tag name="big" action="validate"/>
+        <tag name="pre" action="validate"/>
+        <tag name="code" action="validate"/>
+        <tag name="cite" action="validate"/>
+        <tag name="samp" action="validate"/>
+        <tag name="sub" action="validate"/>
+        <tag name="sup" action="validate"/>
+        <tag name="strike" action="validate"/>
+        <tag name="s" action="validate"/>
+        <tag name="center" action="validate"/>
+        <tag name="blockquote" action="validate"/>
+
+        <tag name="hr" action="validate"/>
+        <tag name="br" action="validate"/>
+
+        <tag name="col" action="validate"/>
+
+        <tag name="font" action="validate">
+            <attribute name="color">
+                <regexp-list>
+                    <regexp name="colorName"/>
+                    <regexp name="colorCode"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="face">
+                <regexp-list>
+                    <regexp value="[\w;, \-]+"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="size">
+                <regexp-list>
+                    <regexp value="(\+|-){0,1}(\d)+"/>
+                </regexp-list>
+            </attribute>
+        </tag>
+
+
+        <!-- Anchor and anchor related tags -->
+
+        <tag name="a" action="validate">
+
+            <!--  onInvalid="filterTag" has been removed as per suggestion at OWASP SJ 2007 - just "name" is valid -->
+            <attribute name="href"/>
+            <attribute name="onFocus"/>
+            <attribute name="onBlur"/>
+            <attribute name="nohref">
+                <regexp-list>
+                    <regexp name="anything"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="rel">
+                <literal-list>
+                    <literal value="nofollow"/>
+                </literal-list>
+            </attribute>
+            <attribute name="name"/>
+            <attribute name="target"/>
+
+        </tag>
+
+        <tag name="map" action="validate"/>
+
+        <!-- base tag removed per demo - this could be enabled with literal-list values you allow -->
+        <!--
+        <tag name="base" action="validate">
+            <attribute name="href"/>
+        </tag>
+        -->
+
+
+        <!-- Stylesheet Tags -->
+
+        <tag name="style" action="validate">
+            <attribute name="type">
+                <literal-list>
+                    <literal value="text/css"/>
+                </literal-list>
+            </attribute>
+            <attribute name="media"/>
+        </tag>
+
+        <tag name="span" action="validate"/>
+
+        <tag name="div" action="validate">
+            <attribute name="align"/>
+        </tag>
+
+
+        <!-- Image & image related tags -->
+
+        <tag name="img" action="validate">
+            <attribute name="src" onInvalid="removeTag">
+                <regexp-list>
+                    <regexp name="onsiteURL"/>
+                    <regexp name="offsiteURL"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="name"/>
+            <attribute name="alt"/>
+            <attribute name="height"/>
+            <attribute name="width"/>
+            <attribute name="border"/>
+            <attribute name="align"/>
+
+            <attribute name="hspace">
+                <regexp-list>
+                    <regexp name="number"/>
+                </regexp-list>
+            </attribute>
+
+            <attribute name="vspace">
+                <regexp-list>
+                    <regexp name="number"/>
+                </regexp-list>
+            </attribute>
+        </tag>
+
+        <!-- no way to do this safely without hooking up the same code to @import to embed the remote stylesheet (malicious user could change offsite resource to be malicious after validation -->
+        <!-- <attribute name="href" onInvalid="removeTag"/>  -->
+
+        <tag name="link" action="validate">
+
+            <!-- <attribute name="href" onInvalid="removeTag"/>  -->
+
+            <attribute name="media"/>
+
+            <attribute name="type" onInvalid="removeTag">
+                <literal-list>
+                    <literal value="text/css"/>
+                    <literal value="application/rss+xml"/>
+                    <literal value="image/x-icon"/>
+                </literal-list>
+            </attribute>
+
+            <attribute name="rel">
+                <literal-list>
+                    <literal value="stylesheet"/>
+                    <literal value="shortcut icon"/>
+                    <literal value="search"/>
+                    <literal value="copyright"/>
+                    <literal value="top"/>
+                    <literal value="alternate"/>
+                </literal-list>
+            </attribute>
+        </tag>
+
+
+        <!-- List tags -->
+
+        <tag name="ul" action="validate"/>
+        <tag name="ol" action="validate"/>
+        <tag name="li" action="validate"/>
+
+
+        <!-- Dictionary tags -->
+
+        <tag name="dd" action="truncate"/>
+        <tag name="dl" action="truncate"/>
+        <tag name="dt" action="truncate"/>
+
+
+        <!-- Table tags (tbody, thead, tfoot)-->
+
+        <tag name="caption" action="validate"/>
+
+        <tag name="thead" action="validate">
+            <attribute name="align"/>
+            <attribute name="char"/>
+            <attribute name="charoff"/>
+            <attribute name="valign"/>
+        </tag>
+
+        <tag name="tbody" action="validate">
+            <attribute name="align"/>
+            <attribute name="char"/>
+            <attribute name="charoff"/>
+            <attribute name="valign"/>
+        </tag>
+
+        <tag name="tfoot" action="validate">
+            <attribute name="align"/>
+            <attribute name="char"/>
+            <attribute name="charoff"/>
+            <attribute name="valign"/>
+        </tag>
+
+        <tag name="table" action="validate">
+            <attribute name="height"/>
+            <attribute name="width"/>
+            <attribute name="border"/>
+            <attribute name="bgcolor"/>
+            <attribute name="cellpadding"/>
+            <attribute name="cellspacing"/>
+            <attribute name="background"/>
+            <attribute name="align"/>
+            <attribute name="noresize">
+                <literal-list>
+                    <literal value="noresize"/>
+                    <literal value=""/>
+                </literal-list>
+            </attribute>
+        </tag>
+
+        <tag name="td" action="validate">
+            <attribute name="background"/>
+            <attribute name="bgcolor"/>
+            <attribute name="abbr"/>
+            <attribute name="axis"/>
+            <attribute name="headers"/>
+            <attribute name="scope"/>
+            <attribute name="nowrap"/>
+            <attribute name="height"/>
+            <attribute name="width"/>
+            <attribute name="align"/>
+            <attribute name="char"/>
+            <attribute name="charoff"/>
+            <attribute name="valign"/>
+            <attribute name="colspan"/>
+            <attribute name="rowspan"/>
+        </tag>
+
+        <tag name="th" action="validate">
+            <attribute name="abbr"/>
+            <attribute name="axis"/>
+            <attribute name="headers"/>
+            <attribute name="scope"/>
+            <attribute name="nowrap"/>
+            <attribute name="bgcolor"/>
+            <attribute name="height"/>
+            <attribute name="width"/>
+            <attribute name="align"/>
+            <attribute name="char"/>
+            <attribute name="charoff"/>
+            <attribute name="valign"/>
+            <attribute name="colspan"/>
+            <attribute name="rowspan"/>
+        </tag>
+
+        <tag name="tr" action="validate">
+            <attribute name="height"/>
+            <attribute name="width"/>
+            <attribute name="align"/>
+            <attribute name="valign"/>
+            <attribute name="char"/>
+            <attribute name="charoff"/>
+            <attribute name="background"/>
+        </tag>
+
+        <tag name="colgroup" action="validate">
+
+            <attribute name="span">
+                <regexp-list>
+                    <regexp name="number"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="width"/>
+            <attribute name="align"/>
+            <attribute name="char"/>
+            <attribute name="charoff"/>
+            <attribute name="valign"/>
+        </tag>
+
+        <tag name="col" action="validate">
+            <attribute name="align"/>
+            <attribute name="char"/>
+            <attribute name="charoff"/>
+            <attribute name="valign"/>
+            <attribute name="span">
+                <regexp-list>
+                    <regexp name="number"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="width"/>
+        </tag>
+
+        <tag name="fieldset" action="validate"/>
+        <tag name="legend" action="validate"/>
+
+
+        <!-- tags for popular Flash embeds -->
+
+        <tag name="object" action="validate">
+            <attribute name="id"/>
+            <attribute name="classid"/>
+            <attribute name="codebase"/>
+            <attribute name="type" onInvalid="removeTag">
+                <literal-list>
+                    <literal value="application/x-shockwave-flash"/>
+                </literal-list>
+            </attribute>
+            <attribute name="data" onInvalid="removeTag">
+                <regexp-list>
+                    <regexp name="flashSites"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="align"/>
+            <attribute name="height"/>
+            <attribute name="width"/>
+            <attribute name="alt"/>
+            <attribute name="bgcolor">
+                <regexp-list>
+                    <regexp name="colorCode"/>
+                </regexp-list>
+            </attribute>
+        </tag>
+
+        <!-- with validateParamAsEmbed=true, this tag rule also covers <param> name/value pairs -->
+        <tag name="embed" action="validate">
+            <attribute name="src" onInvalid="removeTag">
+                <regexp-list>
+                    <regexp name="flashSites"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="movie" onInvalid="removeTag">
+                <regexp-list>
+                    <regexp name="flashSites"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="pluginspage">
+                <regexp-list>
+                    <regexp name="flashSites"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="bgcolor">
+                <regexp-list>
+                    <regexp name="colorCode"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="base">
+                <literal-list>
+                    <literal value="http://admin.brightcove.com"/>
+                </literal-list>
+            </attribute>
+            <attribute name="type">
+                <literal-list>
+                    <literal value="application/x-shockwave-flash"/>
+                </literal-list>
+            </attribute>
+            <attribute name="name">
+                <regexp-list>
+                    <regexp name="anything"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="flashvars">
+                <regexp-list>
+                    <regexp name="anything"/>
+                    <!-- we could put something complex in here, but this is prolly fine for now-->
+                </regexp-list>
+            </attribute>
+            <attribute name="align"/>
+            <attribute name="height"/>
+            <attribute name="width"/>
+            <attribute name="allowfullscreen">
+                <regexp-list>
+                    <regexp name="boolean"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="quality">
+                <literal-list>
+                    <literal value="high"/>
+                </literal-list>
+            </attribute>
+            <attribute name="allowscriptaccess">
+                <literal-list>
+                    <literal value="always"/>
+                    <literal value="samedomain"/>
+                </literal-list>
+            </attribute>
+            <attribute name="seamlesstabbing">
+                <regexp-list>
+                    <regexp name="boolean"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="swliveconnect">
+                <regexp-list>
+                    <regexp name="boolean"/>
+                </regexp-list>
+            </attribute>
+            <attribute name="wmode">
+                <literal-list>
+                    <literal value="transparent"/>
+                    <literal value="window"/>
+                </literal-list>
+            </attribute>
+            <attribute name="allownetworking">
+                <literal-list>
+                    <literal value="all"/>
+                </literal-list>
+            </attribute>
+        </tag>
+
+        <!-- SLING-8771 - HTML5 figure and figcaption http://html5doctor.com/the-figure-figcaption-elements/ -->
+        <tag name="figure" action="validate"/>
+        <tag name="figcaption" action="validate"/>
+
+    </tag-rules>
+
+
+    <!--  CSS validation processing rules  -->
+
+    <css-rules>
+
+        <property name="azimuth"
+                  description="This property is most likely to be implemented by mixing the same signal into different channels at differing volumes.">
+            <literal-list>
+                <literal value="left-side"/>
+                <literal value="far-left"/>
+                <literal value="left"/>
+                <literal value="center-left"/>
+                <literal value="center"/>
+                <literal value="center-right"/>
+                <literal value="right"/>
+                <literal value="far-right"/>
+                <literal value="right-side"/>
+                <literal value="behind"/>
+                <literal value="leftwards"/>
+                <literal value="rightwards"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="angle"/>
+            </regexp-list>
+        </property>
+
+        <property name="background"
+                  description="The 'background' property is a shorthand property for setting the individual background properties (i.e., 'background-color', 'background-image', 'background-repeat', 'background-attachment' and 'background-position') at the same place in the style sheet.">
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="background-color"/>
+                <shorthand name="background-image"/>
+                <shorthand name="background-repeat"/>
+                <shorthand name="background-attachment"/>
+                <shorthand name="background-position"/>
+            </shorthand-list>
+        </property>
+
+        <property name="background-attachment"
+                  description="If a background image is specified, this property specifies whether it is fixed with regard to the viewport ('fixed') or scrolls along with the document ('scroll').">
+            <literal-list>
+                <literal value="scroll"/>
+                <literal value="fixed"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+
+        <property name="background-color"
+                  description="This property sets the background color of an element, either a &lt;color&gt; value or the keyword 'transparent', to make the underlying colors shine through.">
+            <literal-list>
+                <literal value="transparent"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+        </property>
+
+        <property name="background-image" description="This property sets the background image of an element.">
+            <literal-list>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="cssOffsiteUri"/>
+                <regexp name="cssOnsiteUri"/>
+            </regexp-list>
+        </property>
+
+        <property name="background-position"
+                  description="If a background image has been specified, this property specifies its initial position.">
+            <literal-list>
+                <literal value="top"/>
+                <literal value="center"/>
+                <literal value="bottom"/>
+                <literal value="left"/>
+                <literal value="center"/>
+                <literal value="right"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="percentage"/>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+
+        <property name="background-repeat"
+                  description="If a background image is specified, this property specifies whether the image is repeated (tiled), and how.">
+            <literal-list>
+                <literal value="repeat"/>
+                <literal value="repeat-x"/>
+                <literal value="repeat-y"/>
+                <literal value="no-repeat"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+
+        <!-- Begin simple properties -->
+        <property name="border-collapse" default="collapse" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="collapse"/>
+                <literal value="separate"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="border-color" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="transparent"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+        </property>
+        <property name="border-top-color" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+        </property>
+        <property name="border-right-color" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+        </property>
+        <property name="border-bottom-color" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+        </property>
+        <property name="border-left-color" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+        </property>
+        <property name="bottom" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="caption-side" default="top" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="top"/>
+                <literal value="bottom"/>
+                <literal value="left"/>
+                <literal value="right"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="clear" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="left"/>
+                <literal value="right"/>
+                <literal value="both"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="color" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+        </property>
+        <property name="cue-after" default="none" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="cssOffsiteUri"/>
+                <regexp name="cssOnsiteUri"/>
+            </regexp-list>
+        </property>
+        <property name="cue-before" default="none" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="cssOffsiteUri"/>
+                <regexp name="cssOnsiteUri"/>
+            </regexp-list>
+        </property>
+        <property name="direction" default="ltr" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="ltr"/>
+                <literal value="rtl"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="display" default="inline" description="">
+            <category-list>
+                <category value="all"/>
+            </category-list>
+            <literal-list>
+                <literal value="inline"/>
+                <literal value="block"/>
+                <literal value="list-item"/>
+                <literal value="run-in"/>
+                <literal value="compact"/>
+                <literal value="marker"/>
+                <literal value="table"/>
+                <literal value="inline-table"/>
+                <literal value="table-row-group"/>
+                <literal value="table-header-group"/>
+                <literal value="table-footer-group"/>
+                <literal value="table-row"/>
+                <literal value="table-column-group"/>
+                <literal value="table-column"/>
+                <literal value="table-cell"/>
+                <literal value="table-caption"/>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="elevation" default="level" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="below"/>
+                <literal value="level"/>
+                <literal value="above"/>
+                <literal value="higher"/>
+                <literal value="lower"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="angle"/>
+            </regexp-list>
+        </property>
+        <property name="empty-cells" default="show" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="show"/>
+                <literal value="hide"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="float" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="left"/>
+                <literal value="right"/>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="font-size" default="medium" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="absolute-size"/>
+                <regexp name="relative-size"/>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="font-size-adjust" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </property>
+        <property name="font-stretch" default="normal" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="wider"/>
+                <literal value="narrower"/>
+                <literal value="ultra-condensed"/>
+                <literal value="extra-condensed"/>
+                <literal value="condensed"/>
+                <literal value="semi-condensed"/>
+                <literal value="semi-expanded"/>
+                <literal value="expanded"/>
+                <literal value="extra-expanded"/>
+                <literal value="ultra-expanded"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="font-style" default="normal" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="italic"/>
+                <literal value="oblique"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="font-variant" default="normal" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="small-caps"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="font-weight" default="normal" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="bold"/>
+                <literal value="bolder"/>
+                <literal value="lighter"/>
+                <literal value="100"/>
+                <literal value="200"/>
+                <literal value="300"/>
+                <literal value="400"/>
+                <literal value="500"/>
+                <literal value="600"/>
+                <literal value="700"/>
+                <literal value="800"/>
+                <literal value="900"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="height" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="left" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="letter-spacing" default="normal" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+        <property name="line-height" default="normal" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="number"/>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="list-style-image" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="cssOffsiteUri"/>
+                <regexp name="cssOnsiteUri"/>
+            </regexp-list>
+        </property>
+        <property name="list-style-position" default="outside" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inside"/>
+                <literal value="outside"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="list-style-type" default="disc" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="disc"/>
+                <literal value="circle"/>
+                <literal value="square"/>
+                <literal value="decimal"/>
+                <literal value="decimal-leading-zero"/>
+                <literal value="lower-roman"/>
+                <literal value="upper-roman"/>
+                <literal value="lower-greek"/>
+                <literal value="lower-alpha"/>
+                <literal value="lower-latin"/>
+                <literal value="upper-alpha"/>
+                <literal value="upper-latin"/>
+                <literal value="hebrew"/>
+                <literal value="armenian"/>
+                <literal value="georgian"/>
+                <literal value="cjk-ideographic"/>
+                <literal value="hiragana"/>
+                <literal value="katakana"/>
+                <literal value="hiragana-iroha"/>
+                <literal value="katakana-iroha"/>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="marker-offset" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+        <property name="max-height" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="max-width" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="min-height" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="min-width" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="orphans" default="2" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="paged"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="integer"/>
+            </regexp-list>
+        </property>
+        <property name="outline-color" default="invert" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="interactive"/>
+            </category-list>
+            <literal-list>
+                <literal value="invert"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+        </property>
+        <property name="overflow" default="visible" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="visible"/>
+                <literal value="hidden"/>
+                <literal value="scroll"/>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="page-break-after" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="paged"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="always"/>
+                <literal value="avoid"/>
+                <literal value="left"/>
+                <literal value="right"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="page-break-before" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="paged"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="always"/>
+                <literal value="avoid"/>
+                <literal value="left"/>
+                <literal value="right"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="page-break-inside" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="paged"/>
+            </category-list>
+            <literal-list>
+                <literal value="avoid"/>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="pause-after" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="time"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="pause-before" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="time"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="pitch" default="medium" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="x-low"/>
+                <literal value="low"/>
+                <literal value="medium"/>
+                <literal value="high"/>
+                <literal value="x-high"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="frequency"/>
+            </regexp-list>
+        </property>
+        <property name="pitch-range" default="50" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </property>
+        <property name="position" default="static" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="static"/>
+                <!-- possible to perform phishing attacks with the following -->
+                <!--
+                <literal value="relative"/>
+                <literal value="absolute"/>
+                <literal value="fixed"/>
+                 -->
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="richness" default="50" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </property>
+        <property name="right" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="size" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="paged"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="portrait"/>
+                <literal value="landscape"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+        <property name="speak" default="normal" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="none"/>
+                <literal value="spell-out"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="speak-header" default="once" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="once"/>
+                <literal value="always"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="speak-numeral" default="continuous" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="digits"/>
+                <literal value="continuous"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="speak-punctuation" default="none" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="code"/>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="speech-rate" default="medium" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="x-slow"/>
+                <literal value="slow"/>
+                <literal value="medium"/>
+                <literal value="fast"/>
+                <literal value="x-fast"/>
+                <literal value="faster"/>
+                <literal value="slower"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </property>
+        <property name="stress" default="50" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="number"/>
+            </regexp-list>
+        </property>
+        <property name="table-layout" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="fixed"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="text-indent" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="text-transform" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="capitalize"/>
+                <literal value="uppercase"/>
+                <literal value="lowercase"/>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="top" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="unicode-bidi" default="normal" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="embed"/>
+                <literal value="bidi-override"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="vertical-align" default="baseline" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="baseline"/>
+                <literal value="sub"/>
+                <literal value="super"/>
+                <literal value="top"/>
+                <literal value="text-top"/>
+                <literal value="middle"/>
+                <literal value="bottom"/>
+                <literal value="text-bottom"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="percentage"/>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+        <property name="visibility" default="inherit" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="visible"/>
+                <literal value="hidden"/>
+                <literal value="collapse"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="volume" default="medium" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="silent"/>
+                <literal value="x-soft"/>
+                <literal value="soft"/>
+                <literal value="medium"/>
+                <literal value="loud"/>
+                <literal value="x-loud"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="number"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="white-space" default="normal" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="pre"/>
+                <literal value="nowrap"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="widows" default="2" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="paged"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="integer"/>
+            </regexp-list>
+        </property>
+        <property name="width" default="auto" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="word-spacing" default="normal" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="normal"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+
+        <!-- end simple properties -->
+
+        <!-- begin medium properties -->
+        <property name="border-style" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+                <literal value="none"/>
+                <literal value="hidden"/>
+                <literal value="dotted"/>
+                <literal value="dashed"/>
+                <literal value="solid"/>
+                <literal value="double"/>
+                <literal value="groove"/>
+                <literal value="ridge"/>
+                <literal value="inset"/>
+                <literal value="outset"/>
+            </literal-list>
+        </property>
+        <property name="border-top-style" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="border-right-style" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="border-style"/>
+            </shorthand-list>
+        </property>
+        <property name="border-bottom-style" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="border-style"/>
+            </shorthand-list>
+        </property>
+        <property name="border-left-style" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="border-style"/>
+            </shorthand-list>
+        </property>
+        <property name="border-top-width" default="medium" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="border-width"/>
+            </shorthand-list>
+        </property>
+        <property name="border-right-width" default="medium" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="border-width"/>
+            </shorthand-list>
+        </property>
+        <property name="border-bottom-width" default="medium" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="border-width"/>
+            </shorthand-list>
+        </property>
+        <property name="border-left-width" default="medium" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="border-width"/>
+            </shorthand-list>
+        </property>
+        <property name="border-width" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+                <literal value="thin"/>
+                <literal value="medium"/>
+                <literal value="thick"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+        <property name="margin" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+                <literal value="auto"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="positiveLength"/>
+                <regexp name="positivePercentage"/>
+            </regexp-list>
+        </property>
+        <property name="margin-top" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="margin"/>
+            </shorthand-list>
+        </property>
+        <property name="margin-right" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="margin"/>
+            </shorthand-list>
+        </property>
+        <property name="margin-bottom" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="margin"/>
+            </shorthand-list>
+        </property>
+        <property name="margin-left" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="margin"/>
+            </shorthand-list>
+        </property>
+        <property name="outline-style" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="interactive"/>
+            </category-list>
+
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="border-style"/>
+            </shorthand-list>
+        </property>
+        <property name="outline-width" default="medium" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="interactive"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="border-width"/>
+            </shorthand-list>
+        </property>
+        <property name="padding" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="padding-top" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="padding"/>
+            </shorthand-list>
+        </property>
+        <property name="padding-right" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="padding"/>
+            </shorthand-list>
+        </property>
+        <property name="padding-bottom" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="padding"/>
+            </shorthand-list>
+        </property>
+        <property name="padding-left" default="0" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="padding"/>
+            </shorthand-list>
+        </property>
+        <!-- end medium properties -->
+
+        <!-- begin hard properties -->
+        <property name="border" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+            <shorthand-list>
+                <shorthand name="border-width"/>
+                <shorthand name="border-style"/>
+            </shorthand-list>
+        </property>
+        <property name="border-top" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+            <shorthand-list>
+                <shorthand name="border-top-width"/>
+                <shorthand name="border-style"/>
+            </shorthand-list>
+        </property>
+        <property name="border-right" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+            <shorthand-list>
+                <shorthand name="border-top-width"/>
+                <shorthand name="border-style"/>
+            </shorthand-list>
+        </property>
+        <property name="border-bottom" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+            <shorthand-list>
+                <shorthand name="border-top-width"/>
+                <shorthand name="border-style"/>
+            </shorthand-list>
+        </property>
+        <property name="border-left" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+            </regexp-list>
+            <shorthand-list>
+                <shorthand name="border-top-width"/>
+                <shorthand name="border-style"/>
+            </shorthand-list>
+        </property>
+        <property name="cue" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="cue-before"/>
+                <shorthand name="cue-after"/>
+            </shorthand-list>
+        </property>
+        <property name="list-style" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="list-style-type"/>
+                <shorthand name="list-style-position"/>
+                <shorthand name="list-style-image"/>
+            </shorthand-list>
+        </property>
+        <property name="marks" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="paged"/>
+            </category-list>
+            <literal-list>
+                <literal value="crop"/>
+                <literal value="cross"/>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="outline" description="">
+            <category-list>
+                <category value="visual"/>
+                <category value="interactive"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="outline-color"/>
+                <shorthand name="outline-style"/>
+                <shorthand name="outline-width"/>
+            </shorthand-list>
+        </property>
+        <property name="pause" description="">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="time"/>
+                <regexp name="percentage"/>
+            </regexp-list>
+        </property>
+        <property name="text-decoration" default="none" description="">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="underline"/>
+                <literal value="overline"/>
+                <literal value="line-through"/>
+                <literal value="blink"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <!-- end hard properties -->
+        <!--  begin manual properties -->
+        <property name="border-spacing" default="0"
+                  description="The lengths specify the distance that separates adjacent cell borders. If one length is specified, it gives both the horizontal and vertical spacing. If two are specified, the first gives the horizontal spacing and the second the vertical spacing. Lengths may not be negative.">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+        <property name="clip" default="auto"
+                  description="The 'clip' property applies to elements that have a 'overflow' property with a value other than 'visible'.">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+        <property name="counter-increment" default="none"
+                  description="The 'counter-increment' property accepts one or more names of counters (identifiers), each one optionally followed by an integer.">
+            <category-list>
+                <category value="all"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="cssIdentifier"/>
+                <regexp name="integer"/>
+            </regexp-list>
+        </property>
+        <property name="clip" default="auto"
+                  description="The 'clip' property applies to elements that have a 'overflow' property with a value other than 'visible'.">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+        <property name="cursor" default="auto"
+                  description="This property specifies the type of cursor to be displayed for the pointing device.">
+            <category-list>
+                <category value="visual"/>
+                <category value="interactive"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+                <literal value="crosshair"/>
+                <literal value="default"/>
+                <literal value="pointer"/>
+                <literal value="move"/>
+                <literal value="e-resize"/>
+                <literal value="ne-resize"/>
+                <literal value="nw-resize"/>
+                <literal value="n-resize"/>
+                <literal value="se-resize"/>
+                <literal value="sw-resize"/>
+                <literal value="s-resize"/>
+                <literal value="w-resize| text"/>
+                <literal value="wait"/>
+                <literal value="help"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="cssOffsiteUri"/>
+                <regexp name="cssOnsiteUri"/>
+            </regexp-list>
+        </property>
+
+        <property name="text-shadow" default="none"
+                  description="This property accepts a comma-separated list of shadow effects to be applied to the text of the element.">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="none"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="colorName"/>
+                <regexp name="colorCode"/>
+                <regexp name="rgbCode"/>
+                <regexp name="systemColor"/>
+                <regexp name="length"/>
+            </regexp-list>
+        </property>
+
+        <property name="font"
+                  description="The 'font' property is, except as described below, a shorthand property for setting 'font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', and 'font-family', at the same place in the style sheet.">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <literal-list>
+                <literal value="/"/>
+                <literal value="caption"/>
+                <literal value="icon"/>
+                <literal value="menu"/>
+                <literal value="message-box"/>
+                <literal value="small-caption"/>
+                <literal value="status-bar"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <shorthand-list>
+                <shorthand name="font-style"/>
+                <shorthand name="font-variant"/>
+                <shorthand name="font-weight"/>
+                <shorthand name="font-size"/>
+                <shorthand name="line-height"/>
+                <shorthand name="font-family"/>
+            </shorthand-list>
+        </property>
+
+        <property name="font-family"
+                  description="This property specifies a prioritized list of font family names and/or generic family names.">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <!-- allowing only generic font families -->
+            <literal-list>
+                <literal value="serif"/>
+                <literal value="arial"/>
+                <literal value="lucida console"/>
+                <literal value="sans-serif"/>
+                <literal value="cursive"/>
+                <literal value="verdana"/>
+                <literal value="fantasy"/>
+                <literal value="monospace"/>
+            </literal-list>
+
+
+            <regexp-list>
+                <regexp value="[\w,\-&apos;&quot; ]+"/>
+            </regexp-list>
+
+        </property>
+        <property name="page"
+                  description="The 'page' property can be used to specify a particular type of page where an element should be displayed.">
+            <category-list>
+                <category value="visual"/>
+                <category value="paged"/>
+            </category-list>
+            <literal-list>
+                <literal value="auto"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="cssIdentifier"/>
+            </regexp-list>
+        </property>
+        <property name="play-during" default="auto"
+                  description="Similar to the 'cue-before' and 'cue-after' properties, this property specifies a sound to be played as a background while an element's content is spoken.">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <literal-list>
+                <literal value="mix"/>
+                <literal value="repeat"/>
+                <literal value="none"/>
+                <literal value="auto"/>
+                <literal value="inherit"/>
+            </literal-list>
+            <regexp-list>
+                <regexp name="cssOffsiteUri"/>
+                <regexp name="cssOnsiteUri"/>
+            </regexp-list>
+        </property>
+        <property name="text-align" description="This property describes how inline content of a block is aligned.">
+            <category-list>
+                <category value="visual"/>
+            </category-list>
+            <!--  For safety, ignoring string alignment which can be used to line table cells on characters -->
+            <literal-list>
+                <literal value="left"/>
+                <literal value="right"/>
+                <literal value="center"/>
+                <literal value="justify"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <property name="voice-family"
+                  description="The value is a comma-separated, prioritized list of voice family names (compare with 'font-family').">
+            <category-list>
+                <category value="aural"/>
+            </category-list>
+            <!--  Allowing only generic voice family -->
+            <literal-list>
+                <literal value="male"/>
+                <literal value="female"/>
+                <literal value="child"/>
+                <literal value="inherit"/>
+            </literal-list>
+        </property>
+        <!--  end manual properties -->
+    </css-rules>
+
+
+    <allowed-empty-tags>
+        <literal-list>
+            <literal value="br"/>
+            <literal value="hr"/>
+            <literal value="a"/>
+            <literal value="img"/>
+            <literal value="link"/>
+            <literal value="iframe"/>
+            <literal value="script"/>
+            <literal value="object"/>
+            <literal value="applet"/>
+            <literal value="frame"/>
+            <literal value="base"/>
+            <literal value="param"/>
+            <literal value="meta"/>
+            <literal value="input"/>
+            <literal value="textarea"/>
+            <literal value="embed"/>
+            <literal value="basefont"/>
+            <literal value="col"/>
+            <literal value="div"/>
+        </literal-list>
+    </allowed-empty-tags>
+
+</anti-samy-rules>