From: <bo...@us...> - 2013-02-03 10:14:43
|
Revision: 506 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=506&view=rev Author: bodewig Date: 2013-02-03 10:14:36 +0000 (Sun, 03 Feb 2013) Log Message: ----------- Post xsi:type changes to .NET version Modified Paths: -------------- trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs trunk/xmlunit/src/main/net-core/diff/XPathContext.cs trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs trunk/xmlunit/src/tests/net-core/diff/XPathContextTest.cs Modified: trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs =================================================================== --- trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs 2013-02-03 09:41:49 UTC (rev 505) +++ trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs 2013-02-03 10:14:36 UTC (rev 506) @@ -424,6 +424,12 @@ } } + lastResult = CompareXsiType(controlAttributes.Type, controlContext, + testAttributes.Type, testContext); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + lastResult = Compare(new Comparison(ComparisonType.SCHEMA_LOCATION, control, GetXPath(controlContext), @@ -571,7 +577,69 @@ return lastResult; } + /// <summary> + /// Compares xsi:type attribute values + /// </summary> + private ComparisonResult CompareXsiType(XmlAttribute control, + XPathContext controlContext, + XmlAttribute test, + XPathContext testContext) { + bool mustChangeControlContext = control != null; + bool mustChangeTestContext = test != null; + if (!mustChangeControlContext && !mustChangeTestContext) { + return ComparisonResult.EQUAL; + } + + try { + if (mustChangeControlContext) { + XmlQualifiedName q = Nodes.GetQName(control); + controlContext.AddAttribute(q); + controlContext.NavigateToAttribute(q); + } + if (mustChangeTestContext) { + XmlQualifiedName q = Nodes.GetQName(test); + testContext.AddAttribute(q); + testContext.NavigateToAttribute(q); + } + ComparisonResult lastResult = + Compare(new Comparison(ComparisonType.ATTR_NAME_LOOKUP, + control, GetXPath(controlContext), + mustChangeControlContext, + test, GetXPath(testContext), + mustChangeTestContext)); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + if (mustChangeControlContext && mustChangeTestContext) { + lastResult = + CompareAttributeExplicitness(control, controlContext, + test, testContext); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + XmlQualifiedName controlQName = ValueAsQName(control); + XmlQualifiedName testQName = ValueAsQName(test); + lastResult = + Compare(new Comparison(ComparisonType.ATTR_VALUE, + control, + GetXPath(controlContext), + controlQName.ToString(), + test, GetXPath(testContext), + testQName.ToString())); + } + return lastResult; + } finally { + if (mustChangeControlContext) { + controlContext.NavigateToParent(); + } + if (mustChangeTestContext) { + testContext.NavigateToParent(); + } + } + } + + /// <summary> /// Compares properties of an attribute. /// </summary> private ComparisonResult CompareAttributes(XmlAttribute control, @@ -580,11 +648,8 @@ XPathContext testContext) { ComparisonResult lastResult = - Compare(new Comparison(ComparisonType.ATTR_VALUE_EXPLICITLY_SPECIFIED, - control, GetXPath(controlContext), - control.Specified, - test, GetXPath(testContext), - test.Specified)); + CompareAttributeExplicitness(control, controlContext, + test, testContext); if (lastResult == ComparisonResult.CRITICAL) { return lastResult; @@ -598,6 +663,22 @@ } /// <summary> + // Compares whether two attributes are specified explicitly. + /// </summary> + private ComparisonResult + CompareAttributeExplicitness(XmlAttribute control, + XPathContext controlContext, + XmlAttribute test, + XPathContext testContext) { + return + Compare(new Comparison(ComparisonType.ATTR_VALUE_EXPLICITLY_SPECIFIED, + control, GetXPath(controlContext), + control.Specified, + test, GetXPath(testContext), + test.Specified)); + } + + /// <summary> /// Separates XML namespace related attributes from "normal" /// attributes. /// </summary> @@ -608,26 +689,49 @@ XmlAttribute nNsLoc = map.GetNamedItem("noNamespaceSchemaLocation", XmlSchema.InstanceNamespace) as XmlAttribute; + XmlAttribute type = map.GetNamedItem("type", + XmlSchema.InstanceNamespace) + as XmlAttribute; List<XmlAttribute> rest = new List<XmlAttribute>(); foreach (XmlAttribute a in map) { - if (XmlSchema.InstanceNamespace != a.NamespaceURI - && - "http://www.w3.org/2000/xmlns/" != a.NamespaceURI) { + if ("http://www.w3.org/2000/xmlns/" != a.NamespaceURI + && a != sLoc && a != nNsLoc && a != type) { rest.Add(a); } } - return new Attributes(sLoc, nNsLoc, rest); + return new Attributes(sLoc, nNsLoc, type, rest); } + private static XmlQualifiedName ValueAsQName(XmlAttribute attribute) { + // split QName into prefix and local name + string[] pieces = attribute.Value.Split(':'); + if (pieces.Length < 2) { + // unprefixed name + pieces = new string[] { string.Empty, pieces[0] }; + } else if (pieces.Length > 2) { + // actually, this is not a valid QName - be lenient + pieces = new string[] { + pieces[0], + attribute.Value.Substring(pieces[0].Length + 1) + }; + } + return new XmlQualifiedName(pieces[1] ?? string.Empty, + attribute + .GetNamespaceOfPrefix(pieces[0])); + } + internal class Attributes { internal readonly XmlAttribute SchemaLocation; internal readonly XmlAttribute NoNamespaceSchemaLocation; + internal readonly XmlAttribute Type; internal readonly IList<XmlAttribute> RemainingAttributes; internal Attributes(XmlAttribute schemaLocation, XmlAttribute noNamespaceSchemaLocation, + XmlAttribute type, IList<XmlAttribute> remainingAttributes) { this.SchemaLocation = schemaLocation; this.NoNamespaceSchemaLocation = noNamespaceSchemaLocation; + this.Type = type; this.RemainingAttributes = remainingAttributes; } } Modified: trunk/xmlunit/src/main/net-core/diff/XPathContext.cs =================================================================== --- trunk/xmlunit/src/main/net-core/diff/XPathContext.cs 2013-02-03 09:41:49 UTC (rev 505) +++ trunk/xmlunit/src/main/net-core/diff/XPathContext.cs 2013-02-03 10:14:36 UTC (rev 506) @@ -64,6 +64,12 @@ } } + public void AddAttribute(XmlQualifiedName attribute) { + Level current = path.Last.Value; + current.Attributes[attribute] = + new Level(ATTR + GetName(attribute)); + } + public void SetChildren<N>(IEnumerable<N> children) where N : INodeInfo { Level current = path.Last.Value; Modified: trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs =================================================================== --- trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs 2013-02-03 09:41:49 UTC (rev 505) +++ trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs 2013-02-03 10:14:36 UTC (rev 506) @@ -750,5 +750,141 @@ e2, new XPathContext())); Assert.AreEqual(1, ex.invoked); } + + [Test] + public void XsiTypesWithDifferentPrefixes() { + XmlDocument d1 = + DocumentForString("<foo xsi:type='p1:Foo'" + + " xmlns:p1='urn:xmlunit:test'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + XmlDocument d2 = + DocumentForString("<foo xsi:type='p2:Foo'" + + " xmlns:p2='urn:xmlunit:test'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.ATTR_VALUE); + d.DifferenceListener += ex.ComparisonPerformed; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + Assert.AreEqual(ComparisonResult.EQUAL, + d.CompareNodes(d1, new XPathContext(), + d2, new XPathContext())); + } + + [Test] + public void XsiTypesWithDefaultNamespace() { + XmlDocument d1 = + DocumentForString("<a:foo xsi:type='Foo'" + + " xmlns='urn:xmlunit:test'" + + " xmlns:a='urn:xmlunit:test2'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + XmlDocument d2 = + DocumentForString("<a:foo xsi:type='p2:Foo'" + + " xmlns:p2='urn:xmlunit:test'" + + " xmlns:a='urn:xmlunit:test2'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.ATTR_VALUE); + d.DifferenceListener += ex.ComparisonPerformed; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + Assert.AreEqual(ComparisonResult.EQUAL, + d.CompareNodes(d1, new XPathContext(), + d2, new XPathContext())); + } + + [Test] + public void XsiTypesWithDifferentLocalNames() { + XmlDocument d1 = + DocumentForString("<foo xsi:type='p1:Bar'" + + " xmlns:p1='urn:xmlunit:test'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + XmlDocument d2 = + DocumentForString("<foo xsi:type='p1:Foo'" + + " xmlns:p1='urn:xmlunit:test'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.ATTR_VALUE); + d.DifferenceListener += ex.ComparisonPerformed; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + Assert.AreEqual(ComparisonResult.CRITICAL, + d.CompareNodes(d1, new XPathContext(), + d2, new XPathContext())); + } + + [Test] + public void XsiTypesWithDifferentNamespaceURIs() { + XmlDocument d1 = + DocumentForString("<foo xsi:type='p1:Foo'" + + " xmlns:p1='urn:xmlunit:test'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + XmlDocument d2 = + DocumentForString("<foo xsi:type='p1:Foo'" + + " xmlns:p1='urn:xmlunit:test2'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.ATTR_VALUE); + d.DifferenceListener += ex.ComparisonPerformed; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + Assert.AreEqual(ComparisonResult.CRITICAL, + d.CompareNodes(d1, new XPathContext(), + d2, new XPathContext())); + } + + [Test] + public void XsiTypesWithNamespaceDeclarationOnDifferentLevels() { + XmlDocument d1 = + DocumentForString("<bar xmlns:p1='urn:xmlunit:test'>" + + "<foo xsi:type='p1:Foo'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/></bar>"); + XmlDocument d2 = + DocumentForString("<bar><foo xsi:type='p1:Foo'" + + " xmlns:p1='urn:xmlunit:test'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/></bar>"); + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.ATTR_VALUE); + d.DifferenceListener += ex.ComparisonPerformed; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + Assert.AreEqual(ComparisonResult.EQUAL, + d.CompareNodes(d1, new XPathContext(), + d2, new XPathContext())); + } + + [Test] + public void XsiNil() { + XmlDocument d1 = + DocumentForString("<foo xsi:nil='true'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + XmlDocument d2 = + DocumentForString("<foo xsi:nil='false'" + + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" + + "/>"); + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.ATTR_VALUE); + d.DifferenceListener += ex.ComparisonPerformed; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + Assert.AreEqual(ComparisonResult.CRITICAL, + d.CompareNodes(d1, new XPathContext(), + d2, new XPathContext())); + } + + private XmlDocument DocumentForString(string s) { + return net.sf.xmlunit.util.Convert.ToDocument(Input.FromMemory(s).Build()); + } } } Modified: trunk/xmlunit/src/tests/net-core/diff/XPathContextTest.cs =================================================================== --- trunk/xmlunit/src/tests/net-core/diff/XPathContextTest.cs 2013-02-03 09:41:49 UTC (rev 505) +++ trunk/xmlunit/src/tests/net-core/diff/XPathContextTest.cs 2013-02-03 10:14:36 UTC (rev 506) @@ -106,6 +106,16 @@ } [Test] + public void singleAttribute() { + XPathContext ctx = new XPathContext(); + ctx.SetChildren(Linqy.Singleton(new Element("foo"))); + ctx.NavigateToChild(0); + ctx.AddAttribute(new XmlQualifiedName("bar")); + ctx.NavigateToAttribute(new XmlQualifiedName("bar")); + Assert.AreEqual("/foo[1]/@bar", ctx.XPath); + } + + [Test] public void Mixed() { List<XPathContext.INodeInfo> l = new List<XPathContext.INodeInfo>(); l.Add(new Text()); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |