我有一个VB.NET函数,可以验证我的XML与模式,然后如果失败则输出Web服务的XML响应失败。
我遇到的问题是,当我说格式正确的XML时,它会验证并成功,然后如果我发送错误的XML,验证器会正确地说明验证失败的地方。
如果我然后通过Web服务正确发送格式正确的XML,则我的验证检查功能会返回与检查以前的XML时相同的错误,几乎就像它的“缓存”一样。这个问题。
任何人都可以告诉我为什么会这样,我可以确认通过验证的XML是100%正确的,因为我已经查看并导出到我的另一个VB.NET之外的程序验证了XML。
我的ValidateXML函数
Public Shared Function ValidateXML(xmlFilePath As String) As String
Dim doc As New XmlDocument()
doc.LoadXml(xmlFilePath)
doc.Schemas.Add(Nothing, "http://www.fresh.co.uk/freshit/fresh_lead_schema.xsd")
Dim errorBuilder As New XmlValidationErrorBuilder()
doc.Validate(New ValidationEventHandler(AddressOf XmlValidationErrorBuilder.ValidationEventHandler))
FIGCloud.errorsText = XmlValidationErrorBuilder.GetErrors()
If FIGCloud.errorsText IsNot Nothing Then
'Throw New Exception(errorsText)
Return "Failed"
Else
Dim ReturnText As String = doc.InnerXml 'Returns XML Document as a String
Return ReturnText
End If
End Function
我从其他来源获取的XMLvalidationErrorBuilder类
Public Class XmlValidationErrorBuilder
Public Shared _errors As New List(Of ValidationEventArgs)()
Public Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)
If args.Severity = XmlSeverityType.Error Then
_errors.Add(args)
End If
End Sub
Public Shared Function GetErrors() As String
If _errors.Count <> 0 Then
Dim builder As New StringBuilder()
builder.Append("The following ")
builder.Append(_errors.Count.ToString())
builder.AppendLine(" error(s) were found while validating the XML document against the XSD:")
For Each i As ValidationEventArgs In _errors
builder.Append("* ")
builder.AppendLine(i.Message)
Next
Return builder.ToString()
Else
Return Nothing
End If
End Function
End Class
这是正确的格式化XML
<FreshLead>
<ContactDetails>
<Title>Mr</Title>
<FirstName>Joe</FirstName>
<LastName>Bloggs</LastName>
<EmailAddress>joe.bloggs@davisco.co.uk</EmailAddress>
<HomeTel>01527 321 850</HomeTel>
<MobileTel>07771111111</MobileTel>
<DateOfBirth>21/05/1987</DateOfBirth>
<Address>Joe Bloggs Road, Here</Address>
<Postcode>B98 9PA</Postcode>
</ContactDetails>
<TradeDetails>
<TradingName>Motor Trade Direct</TradingName>
<TypeOfBus>Sales</TypeOfBus>
<AgeOfBus>5 Years</AgeOfBus>
<NoOfEmployees>5</NoOfEmployees>
<NoOfDrivers>5</NoOfDrivers>
<FullPartTime>Full-Time</FullPartTime>
<BusPostcode>B98 9PA</BusPostcode>
<BusPremises>No</BusPremises>
<DemoCover>No</DemoCover>
<PremIndem>10000</PremIndem>
<RoadRisksIndem>20000</RoadRisksIndem>
<VolXS>250</VolXS>
<CoverStart>19/03/2015</CoverStart>
<CoverReq>Comprehensive</CoverReq>
<MTExperience>5 Years</MTExperience>
</TradeDetails>
<ProposerDetails>
<UKResident>5 Years</UKResident>
<FullUKLic>10 Years+</FullUKLic>
<MT.NCB>2 Years</MT.NCB>
<PC.NCB>2 Years</PC.NCB>
<ClaimsConv5yr>No</ClaimsConv5yr>
</ProposerDetails>
<AddDetails>
<CurrInsurer>Markerstudy</CurrInsurer>
<BestQuote>2000.00</BestQuote>
<ContactTime>Evening</ContactTime>
<PrefContact>Email</PrefContact>
</AddDetails>
第一次通过Web服务发送时,这会正确验证。
我刚刚更改了两个字段,以便它们包含&#39;字符串&#39;在&#39; Int16&#39;字段然后失败(因为它应该)这些字段是&#39; Indem&#39;字段。
<FreshLead>
<ContactDetails>
<Title>Mr</Title>
<FirstName>Joe</FirstName>
<LastName>Bloggs</LastName>
<EmailAddress>joe.bloggs@davisco.co.uk</EmailAddress>
<HomeTel>01527 321 850</HomeTel>
<MobileTel>07771111111</MobileTel>
<DateOfBirth>21/05/1987</DateOfBirth>
<Address>Joe Bloggs Road, Here</Address>
<Postcode>B98 9PA</Postcode>
</ContactDetails>
<TradeDetails>
<TradingName>Motor Trade Direct</TradingName>
<TypeOfBus>Sales</TypeOfBus>
<AgeOfBus>5 Years</AgeOfBus>
<NoOfEmployees>5</NoOfEmployees>
<NoOfDrivers>5</NoOfDrivers>
<FullPartTime>Full-Time</FullPartTime>
<BusPostcode>B98 9PA</BusPostcode>
<BusPremises>No</BusPremises>
<DemoCover>No</DemoCover>
<PremIndem>Over 10000</PremIndem>
<RoadRisksIndem>Over 20000</RoadRisksIndem>
<VolXS>250</VolXS>
<CoverStart>19/03/2015</CoverStart>
<CoverReq>Comprehensive</CoverReq>
<MTExperience>5 Years</MTExperience>
</TradeDetails>
<ProposerDetails>
<UKResident>5 Years</UKResident>
<FullUKLic>10 Years+</FullUKLic>
<MT.NCB>2 Years</MT.NCB>
<PC.NCB>2 Years</PC.NCB>
<ClaimsConv5yr>No</ClaimsConv5yr>
</ProposerDetails>
<AddDetails>
<CurrInsurer>Markerstudy</CurrInsurer>
<BestQuote>2000.00</BestQuote>
<ContactTime>Evening</ContactTime>
<PrefContact>Email</PrefContact>
</AddDetails>
但是,当我通过它传递第一个工作示例失败并出现与上述XML相同的错误时,我已经在我的代码中提供了它验证的模式的位置,对于任何希望使用工作示例和数字的人来说在我出错的地方。
由于
答案 0 :(得分:3)
在我的original example中,XmlValidationErrorBuilder
类的目的是提供有状态对象,其中每个对象可用于存储单个操作的错误列表。每次执行验证时,它都会创建XmlValidationErrorBuilder
类的新实例,然后使用该本地对象存储仅针对该一个操作的所有错误。验证操作完成后,将从中读取错误并将其丢弃。换句话说,每个验证操作在其自己的本地XmlValidationErrorBuilder
对象中保留了它自己的错误的单独列表。
您的解决方案中的问题是您已将多个成员从实例成员更改为Shared
成员。例如,在我的原始示例中,XmlValidationErrorBuilder
类看起来像这样:
Public Class XmlValidationErrorBuilder
Private _errors As New List(Of ValidationEventArgs)()
Public Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)
If args.Severity = XmlSeverityType.Error Then
_errors.Add(args)
End If
End Sub
Public Function GetErrors() As String
If _errors.Count <> 0 Then
Dim builder As New StringBuilder()
builder.Append("The following ")
builder.Append(_errors.Count.ToString())
builder.AppendLine(" error(s) were found while validating the XML document against the XSD:")
For Each i As ValidationEventArgs In _errors
builder.Append("* ")
builder.AppendLine(i.Message)
Next
Return builder.ToString()
Else
Return Nothing
End If
End Sub
End Class
但是在您的解决方案中,您将两种方法和_errors
字段更改为Shared
成员。这意味着对错误构建器的所有调用将始终在相同的错误列表上工作,无论哪个验证操作正在使用它。
另外,在我的原始示例中,我将委托传递给错误构建器的方法,如下所示:
Dim errorBuilder As New XmlValidationErrorBuilder()
doc.Validate(New ValidationEventHandler(AddressOf errorBuilder.ValidationEventHandler))
如您所见,它创建了错误构建器的全新本地实例,并将对其方法的引用传递给Validate
方法。但是,在您的解决方案中,您将委托传递给Shared
方法,如下所示:
doc.Validate(New ValidationEventHandler(AddressOf XmlValidationErrorBuilder.ValidationEventHandler))
因此,在您的解决方案中,每次调用Validate
时,您都会将代理传递给相同的Shared
方法,然后该方法会使用单个Shared
字段来存储错误。只要您将字段声明为Shared
,它就会创建全局状态。 Global
和Private Shared
字段之间的唯一区别是可访问性级别,但只要它们可访问,它们仍然以相同的方式工作并且用于相同的目的。换句话说,将Private Shared
视为私有全局变量。所以,你可以说你的解决方案之所以“好像它'缓存'这个问题”,是因为它正在缓存本质上是一个全局变量的问题。
答案 1 :(得分:0)
我最终将代码简化为以下
Public Shared Function ValidateXMLv2(ByVal strXML As String, ByVal xsdPath As String) As Boolean
Try
Dim schema As XmlReader = XmlReader.Create(xsdPath)
Dim document As XmlDocument = New XmlDocument()
document.LoadXml(strXML)
document.Schemas.Add("", schema)
Dim eventHandler As ValidationEventHandler = New ValidationEventHandler(AddressOf ValidationEventHandler)
document.Validate(AddressOf ValidationEventHandler)
' the following call to Validate succeeds.
If FIGCloud.validationerrors = "" Then
Return True
Else
Return False
End If
Catch ex As Exception
MsgBox(ex.Message & Environment.NewLine & ex.StackTrace)
Console.WriteLine(ex.Message & Environment.NewLine & ex.StackTrace)
Throw
End Try
End Function
Public Shared Sub ValidationEventHandler(ByVal sender As Object, ByVal e As ValidationEventArgs)
FIGCloud.validationerrors += e.Message & Environment.NewLine
End Sub
然后在函数之外我将FIGCloud.validationerrors设置为“”。