I try to validate a docbook 5.0 xml via c# and xsd data.
I started from the example here: http://msdn.microsoft.com/en-us/library/ckztbtx6(v=vs.110).aspx where it is pretty easy and simple.
I made the notValidXSD.xml (in the example) valid removing the first book calling it nowValidXSD.xml and it words fine.
Now I tried the same for the Docbook 5.0 format ( docbook.xsd, xml.xsd xlink.xml ) which you can download here http://www.docbook.org/xml/5.0/xsd/
Trying the code (given by the example on msdn above) gives me:
Validating XML file mydocxml.xml
Validation error: the http ://www.w3.org/XML/1998/namespace:id-Attribute is not declared.
Validation error: the http ://docbook.org/ns/docbook:article-Element is not declared.
Validation error: the schema informationen für das Attribute 'version' could not be found.
Validation error: the http://docbook.org/ns/docbook:title-Element is not declared.
Validation error: the http://docbook.org/ns/docbook:para-Element is not declared.
Validation finished. Validation failed.
(I had to make spaces after http because its my first question here)
I don't know what to do any more. For me the files look fine. I tried Googling the problem for hours now and can't seem to be able to validate via c#.
Here are the files:
<!-- nowValidXSD.xml -->
<?xml version='1.0' encoding="UTF-8"?>
<bookstore xmlns="urn:bookstore-schema"
xmlns:xsi="http ://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:bookstore-schema books.xsd">
<book genre="novel">
<title>The Confidence Man</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
</bookstore>
And the docbook xml:
<!-- mydocxml.xml -->
<?xml version="1.0" encoding="UTF-8"?> <!-- -->
<article xmlns="http ://docbook.org/ns/docbook" version="5.0"
xmlns:xsi="http ://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http ://docbook.org/ns/docbook docbook.xsd">
<title>some title</title>
<para> some text.</para>
</article>
The problem was that XmlValidatingReader is not only obsolete it is also not doing what is is supposed to be doing.
I post my new Validation method basically from here: http://msdn.microsoft.com/en-US/library/as3tta56(v=vs.80).aspx in hopes that is helps someone :)
private Boolean m_success = true;
private void ValidationCallBack(object sender, ValidationEventArgs args)
{
m_success = false;
Console.WriteLine("\r\n\tValidation error: " + args.Message);
}
public void validate(string xmlfile, string ns, string xsdfile)
{
m_success = true;
XmlReaderSettings settings = new XmlReaderSettings();
XmlSchemaSet sc = new XmlSchemaSet();
sc.Add(ns, xsdfile);
settings.ValidationType = ValidationType.Schema;
settings.Schemas = sc;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
XmlReader reader = XmlReader.Create(xmlfile, settings);
// Parse the file.
while (reader.Read()) ;
Console.WriteLine("Validation finished. Validation {0}", (m_success == true ? "successful!" : "failed."));
reader.Close();
}
Related
I have an XML file which starts something like this:-
<?xml version="1.0" encoding="UTF-8"?>
<Deal xmlns="http://schemas.datacontract.org/2004/07/DealioCapLinkLib.Dealio.Models" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<AccountingDate>2019-09-30</AccountingDate>
When I try to convert this object to XML like below, I get an error:-
private static void Prod_Error_Test()
{
string prodRequestXml = File.ReadAllText("ProdXml.xml");
var serializer = new XmlSerializer(typeof(Service.Deal));
Service.Deal request ;
var reader = new StringReader(prodRequestXml);
request = (Service.Deal)serializer.Deserialize(reader);
}
The Error Message is "There is an error in XML document (2, 2).". The Inner Exception Message is "<Deal xmlns='http://schemas.datacontract.org/2004/07/DealioCapLinkLib.Dealio.Models'> was not expected."
Service.Deal is a WCF Proxy.So I may not be able to add any attributes. Can anyone suggest what to do here ?
Being a WCF proxy doesn't preclude adding attributes; in particular, it is usually a partial class, which means you can have your own separate file, with:
namespace Service
{
[XmlRoot("Deal", Namespace = "http://schemas.datacontract.org/2004/07/DealioCapLinkLib.Dealio.Models")]
partial class Deal {}
}
But ultimately: if the type doesn't conveniently fit the XML: stop fighting it - create a new separate type that fits the XML and works well with XmlSerializer, and then map between the two types in your own code.
I am writing a routine in C# to validate an Xml file using XmlDocument. Everything seems to be fine except something that i cant understand.
my xml:
<?xml version="1.0" encoding="utf-8"?>
<bdo_fosfec:RegistrosPagosElement xsi:type="bdo_fosfec:RegistrosPagos"
xmlns:bdo_fosfec="http://asocajas.hp.com/bdo_fosfec"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<registro54 xsi:type="bdo_fosfec:Registro54">
<registro82 xsi:type="bdo_fosfec:Registro82">
...
</registro82>
</registro54>
<registro54 xsi:type="bdo_fosfec:Registro54">
<registro82 xsi:type="bdo_fosfec:Registro82">
...
</registro82>
</registro54>
</bdo_fosfec:RegistrosPagosElement>
and the xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://asocajas.hp.com/bdo_fosfec" xmlns:tns1="http://asocajas.hp.com/bdo_fosfec" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://asocajas.hp.com/bdo_fosfec">
<xsd:annotation>
<xsd:documentation>BOMORIGIN::platform:/resource/bdo_Fosfec/Business%20Objects/bdo_Fosfec.bom#_rs4Sa9itEeSR9aIqvSWzoQ</xsd:documentation>
</xsd:annotation>
...
</xsd:schema>
here is my code to validate my xml against xsd,
XmlDocument xml = new XmlDocument();
xml.Schemas.Add("http://asocajas.hp.com/bdo_fosfec", PathFileXSD);
//load my xml
xml.LoadXml(stringXml);
//event handler to manage the errors from XmlDocument object
ValidationEventHandler veh = new ValidationEventHandler(ErrorValidacion);
//validate my xml
xml.Validate(veh);
and the event handler ErrorValidacion will show me the error
private void ErrorValidacion(object sender, ValidationEventArgs e)
{
string concat = string.Empty;
switch (e.Severity)
{
case XmlSeverityType.Error:
concat = string.Format("Error: {0}", e.Message);
break;
case XmlSeverityType.Warning:
concat = string.Format("Warning {0}", e.Message);
break;
}
}
When run my program the error msj is:
This is an invalid xsi:type 'http://asocajas.hp.com/bdo_fosfec:RegistrosPagos'.
The thing is.. why this message?, The xsi:type for my xml isn't
http://asocajas.hp.com/bdo_fosfec:RegistrosPagos
The xsi:type for my xml is
xsi:type="bdo_fosfec:RegistrosPagos"
Where does the xsi:type http://asocajas.hp.com/bdo_fosfec:RegistrosPagos come from?
So, How can I solve this issue without having to modify the xml? (Because the xml is based on an xslt)
The error message is saying that the XSD does not include a declaration for RegistrosPagos in the http://asocajas.hp.com/bdo_fosfec namespace.
It is using the expanded form of the namespace to report the error instead of the namespace prefix because the namespace prefix is arbitrary and insignificant by definition. This is entirely proper.
In fact, the XSD you've posted does not include a RegistrosPagos in the http://asocajas.hp.com/bdo_fosfec namespace.
See also: How to restrict the value of an XML element using xsi:type in XSD?
This question already has an answer here:
Error: "The node to be inserted is from a different document context"
(1 answer)
Closed 8 years ago.
I am using XML as discuss forum in ASP.NET. I am trying to add functionality for updating comments. My XML structure is this:
<forum>
<author id="1">
<comment id="0" idUser="19">
<name>....</name>
<date>....</date>
<message>...</message>
</comment>
<comment id="1" idUser="4">
....
</comment>
</author>
<author id="2">
....
</author>
</forum>
And my code is:
protected void btnEditComment_Click(object sender, EventArgs e)
{
if (messageTxb.Text!="" && nameTxb.Text!="")
{
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("~/App_Data/forum.xml"));
XmlNode newComment = (XmlNode)Session["Comment"];
XmlNode oldComment = doc.SelectSingleNode(string.Format("//author[#id={0}]/comment[#id={1}]",Request.QueryString["id"],newComment.Attributes["id"].Value));
newComment.ChildNodes[0].InnerText = nameTxb.Text.Trim();
newComment.ChildNodes[1].InnerText = string.Format("{0:D}", DateTime.Now);
newComment.ChildNodes[2].InnerText = messageTxb.Text.Trim();
oldComment.ParentNode.ReplaceChild(newComment, oldComment);
doc.Save(Server.MapPath("~/App_Data/forum.xml"));
Repeater1.DataBind();
Response.Redirect(string.Format("~/user/Autor.aspx?id={0}", Request.QueryString["id"]));
}
}
I get error
'The node to be inserted is from a different document context.'
It raises when I am trying to use the replaceChild method.
try to replace this row:
oldComment.ParentNode.ReplaceChild(doc.ImportNode(newComment, true), oldComment);
I have seen a couple of examples on here where Xpath is used in conjunction with XmlDocument to get a specific attribute from an XmlDocument Node.... Example
Console.WriteLine(xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element/#name").Value.ToString());
For some reason I am getting a "Object reference not set to an instance of an object." exception. Whenever I run across that particular line of code. I have a little test app that I have set up to test out different things before I put them into my main project...
Here is the code for that...
namespace ReadXml
{
class Program
{
static void Main(string[] args)
{
//string fulXmlPath = System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/templateExample.xml");
XDocument xDocument = XDocument.Load("C:\\Users\\derekww\\Documents\\XML Documents\\templateExample.xml");
XElement elem = xDocument.Element("dataTemplateSpecification"); ;
XmlDocument xmlDocument = new XmlDocument();
StreamReader file = new StreamReader("C:\\Users\\derekww\\Documents\\XML Documents\\templateExample.xml");
xmlDocument.Load(file);
//XmlDocument theDoc = new XmlDocument();
//using (var xmlReader = xDocument.CreateReader())
//{
// xmlDocument.Load(xmlReader);
//}
//Console.WriteLine(elem.ToString());
XmlNode xNode = xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element");
Console.WriteLine("WORK PLEASE!!!! {0}", xNode.Value.ToString());
//Console.WriteLine(xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element/#name").Value.ToString());
//Console.WriteLine("This better Work>>>> {0}", xmlDocument.Attributes["/dataTemplateSpecification/templates/template/elements/element/#name"].Value);
Console.ReadLine();
//Console.WriteLine("This better Work>>>> {0}", xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element/#name").Value);
//foreach (String AttVal in xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element/#name").Value)
{
//Console.WriteLine("This better Work>>>> {0}", AttVal);
}
}
}
}
Here is part of the XML that I used...
<?xml version="1.0" encoding="utf-8"?>
<dataTemplateSpecification id="id1" name="name1" xmlns="http://EADIS.upmc.com /DataTemplateSpecification.xsd">
<description xmlns="">
<html>text</html>
</description>
<templates xmlns="">
<template>
<elements>
<element id="element0" name="PatientId" display="Patient ID" dataType="String" value="0101010111111" visable="false" readOnly="true">
<validation>
<rules>
<rule id="0" test="#element0.value == ''">
<fail>
<html><b>Patient ID is null, value must be present</b></html>
</fail>
</rule>
</rules>
</validation>
</element>
</elements>
</template>
<templates>
I just showed you the part that you need to understand the xml structure. I assure you that it is well formed. I think I asked this question before but somehow or the other it didn't get posted (maybe I forgot, who knows). Any help with this would be greatly appreciated. If I come up with a reason for why it isn't working I will be sure to let you guys know.
Thank You.
Why can't you use this XPath:
xmlDocument.SelectSingleNode("//templates/template/elements/element/#name").Value
You need to specify the namespace of the XML file in your code.
See here for more info: How to select xml root node when root node has attribute?
I don't want to do anything fancy, I just want to make sure a document is valid, and print an error message if it is not. Google pointed me to this, but it seems XmlValidatingReader is obsolete (at least, that's what MonoDevelop tells me).
Edit: I'm trying Mehrdad's tip, but I'm having trouble. I think I've got most of it, but I can't find OnValidationEvent anywhere. Where go I get OnValidationEvent from?
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.DTD;
settings.ValidationEventHandler += new ValidationEventHandler(/*trouble is here*/);
XmlReader validatingReader = XmlReader.Create(fileToLoad, settings);
Instead of creating XmlValidatingReader class directly, you should construct an appropriate XmlReaderSettings object and pass it as an argument to the XmlReader.Create method:
var settings = new XmlReaderSettings { ValidationType = ValidationType.DTD };
settings.ValidationEventHandler += new ValidationEventHandler(OnValidationEvent);
var reader = XmlReader.Create("file.xml", settings);
The rest is unchanged.
P.S. OnValidationEvent is the name of the method you declare to handle validation events. Obviously, you can remove the line if you don't want to subscribe to validation events raised by the XmlReader.
var messages = new StringBuilder();
var settings = new XmlReaderSettings { ValidationType = ValidationType.DTD };
settings.ValidationEventHandler += (sender, args) => messages.AppendLine(args.Message);
var reader = XmlReader.Create("file.xml", settings);
if (messages.Length > 0)
{
// Log Validation Errors
// Throw Exception
// Etc.
}
ValidationEventHandler
Lambda Expressions
Type Inference
I've referred to this example on DTD validation.
https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlreadersettings.dtdprocessing?view=netcore-3.1#input
This example has invalid DTD XML, which I've corrected as below.
<!--XML file using a DTD-->
<!DOCTYPE store [
<!ELEMENT store (item)*>
<!ELEMENT item (name,dept,price)>
<!ATTLIST item type CDATA #REQUIRED ISBN CDATA
#REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT dept (#PCDATA)>
<!ELEMENT price (#PCDATA)>]>
<store>
<item type="supplies" ISBN="2-3631-4">
<name>paint</name>
<dept>1</dept>
<price>16.95</price>
</item>
</store>
full description:
In Visual Studio .NET, create a new Visual C# Console Application
project named ValidateXml. Add two using statements to the beginning
of Class1.cs as follows:
using System.Xml; // for XmlTextReader and XmlValidatingReader
using System.Xml.Schema; // for XmlSchemaCollection (which is used later)
In Class1.cs, declare a boolean variable named isValid before the
start of the Main method as follows:
private static bool isValid = true; // If a validation error occurs,
// set this flag to false in the
// validation event handler.
Create an XmlTextReader object to read an XML document from a text
file in the Main method, and then create an XmlValidatingReader to
validate this XML data as follows:
XmlTextReader r = new XmlTextReader("C:\\MyFolder\\ProductWithDTD.xml");
XmlValidatingReader v = new XmlValidatingReader(r);
The ValidationType property of the XmlValidatingReader object
indicates the type of validation that is required (DTD, XDR, or
Schema). Set this property to DTD as follows:
v.ValidationType = ValidationType.DTD;
If any validation errors occur, the validating reader generates a
validation event. Add the following code to register a validation
event handler (you will implement the MyValidationEventHandler
method in Step 7):
v.ValidationEventHandler +=
new ValidationEventHandler(MyValidationEventHandler);
Add the following code to read and validate the XML document. If any
validation errors occur, MyValidationEventHandler is called to
address the error. This method sets isValid to false (see Step 8).
You can check the status of isValid after validation to see if the
document is valid or invalid.
while (v.Read())
{
// Can add code here to process the content.
}
v.Close();
// Check whether the document is valid or invalid.
if (isValid)
Console.WriteLine("Document is valid");
else
Console.WriteLine("Document is invalid");
Write the MyValidationEventHandler method after the Main method as
follows:
public static void MyValidationEventHandler(object sender,
ValidationEventArgs args)
{
isValid = false;
Console.WriteLine("Validation event\n" + args.Message);
}
Build and run the application. The application should report that the XML document is valid.
e.g.:
In Visual Studio .NET, modify ProductWithDTD.xml to invalidate it (for example, delete the <AuthorName>M soliman</AuthorName> element).
Run the application again. You should receive the following error message:
Validation event
Element 'Product' has invalid content. Expected 'ProductName'.
An error occurred at file:///C:/MyFolder/ProductWithDTD.xml(4, 5).
Document is invalid