Does anyone know how to generate an XSD using LinqToXml? I can't find any examples of this anywhere. The XSD will be of the following fairly low level of complexity:
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML Studio 6.1.18.0 - FREE Community Edition (http://www.liquid-technologies.com)-->
<xs:schema
elementFormDefault="qualified"
targetNamespace="http://schemas.xxx.yy/CRM/2009/01/DeadAnimalReport"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Name">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="35" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Email" type="xs:string" />
<xs:element name="Selection">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="15" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="DeliveryDate" type="xs:date" />
</xs:schema>
The context construction of tooling to allow business analysts to generate message schemas along with some related artefacts that are out of scope of the question. The tooling XSD will be generated from CLR objects in the application's object model.
The objects are pretty simple - a root object that contains enough information to construct the namespace along with a collection of other objects representing the elements (type, name, etc).
Thanks
Sean
Why do you want to use LINQ in this scenario? How does the source data look like?
Not much information given but anyway:
You can construct your XSD using similar code:
XNamespace nsXS = "http://www.w3.org/2001/XMLSchema";
XElement root = new XElement(nsXS + "schema",
new XAttribute("elementFormDefault", "qualified"),
new XAttribute("targetNamespace", "http://schemas.xxx.yy/CRM/2009/01/DeadAnimalReport"),
new XElement(nsXS + "element",
new XElement(nsXS + "simpleType",
new XElement(nsXS + "restriction",
new XAttribute("base", "xs:string")),
new XElement(nsXS + "length", new XAttribute("value", 35)))));
If you have some sort of objects, then you can use projections:
var q =
new XElement(nsXS + "schema",
from s in someObjects
select GetXsdDefinition(s)
);
where
GetXsdDefinition is a method that takes your object as an argument and returns it's XSD definition
Since you want to use LinqToXml, I assume your scenario is that you already have some Xml and you want an Xsd to go with it.
LinqToXml doesn't really have much to do with Xsd's...
You may want to look at Xsd Inference tools.
There is also a LINQ to XSD, maybe thats what you`re looking for!
You can find it HERE
Related
I am updating an XML file in an exist-db collection and I have to check if and id is present to decide if I have to replace or insert something in my document.
I noticed that as the file grows the query execution time worsens significantly and I decided to add an index for my file.
I understand that I have to do that in the conf.xml of my exist-db as it is shown in this example:
<!-- Range indexes -->
<create qname="title" type="xs:string"/>
<create qname="author" type="xs:string"/>
<create qname="year" type="xs:integer"/>
<!-- "old" context-dependant configuration using the path attribute: -->
<create path="//booktitle" type="xs:string"/>
I want to add an index for the attribute id in an xml like the following:
<server>
<formal>
<lastimage>
<harvested>
<coverages>
<coverage active="true" id="EUDEM">
...
</coverage>
</coverages>
</harvested>
</lastimage>
</formal>
</server>
I don't think that adding
<create qname="id" type="xs:string"/>
is enough.
What is the right way of adding and index in exist-db for this attribute?
You're close! Just add # to the beginning of the qname attribute:
<create qname="#id" type="xs:string"/>
The relevant section of the documentation is Configuration by path vs. configuration by qname:
Attributes are specified by #attributeName, so if the attribute is called "attrib1", one uses #attrib1 in the index specification.
I would like to re-use a specific from different *Mapper.xml files which all somehow read same objects.
I have a Database table called Project, which I created the following resultMap for:
<resultMap id="ProjectMap" type="com.model.Project">
<id column="id" jdbcType="BIGINT" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="client_prj_no" jdbcType="VARCHAR" property="clientPrjNo" />
<result column="notes" jdbcType="VARCHAR" property="notes" />
<result column="start_date" jdbcType="TIMESTAMP" property="startDate" />
...
<resultMap>
It works great in the ProjectMapper.xml, however, now I want to create a ClientWithProjectsMapper.xml where I want to SELECT * FROM CLIENT, PROJECT where PROJECT.CLIENT_ID = CLIENT.ID and have a Client object return with a List objects. In other words, I want to get a ClientWithProjects with a single SQL.
In my mapping, I want to reuse the ProjectMap (without copy/paste) which I defined in the ProjectMapper.xml, but I am not sure how to accomplish this.
I could factor out the ProjectMap into a separate file, but I have not found any facilities in MyBatis to #include other files.
Any ideas on how this can be done? (I am using Maven, are there any plugins that would filter the files looking for #include or such, and include the contents of the file right into file being processed?).
Thanks.
-AP_
Once you import all the mapper xmls in mybatis-config.xml file you can refer ResultMaps configured in any of the mapper xmls using resultMap id along with namespace.
for Ex:
ProjectMapper.xml
<mapper namespace="com.mybatisapp.mappers.ProjectMapper">
<resultMap id="ProjectMap" type="com.model.Project">
<id column="id" jdbcType="BIGINT" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<resultMap>
</mapper>
In ClientWithProjectsMapper.xml
<select id="selectProjectsByClient" parameterType="int"
resultMap="com.mybatisapp.mappers.ProjectMapper.ProjectMap">
select * from blahblah
</select>
Here you can reference resultMap in another Mapper xml files using fully qualified name as "com.mybatisapp.mappers.ProjectMapper.ProjectMap"
I am using savon 0.9.2 and ruby 1.8.7.
I am trying to make a complex type soap request.
I need to figure out how to code the soap body for the below type of request using ruby and savon. Basically one of the complextypes in the request extends another type and also needs to be encoded as an array.
The soap request object is supposed to look like this.
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:app="http://someurl/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<soapenv:Header/>
<soapenv:Body>
<app:someMethod soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<xyzResReq xsi:type="java:xyzResReq" xmlns:java="java:com.xyz.request">
<somestring xsi:type="xsd:string">abc123</somestring>
<itinerary xsi:type="java1:xyzItinerary" xmlns:java1="java:com.xyz.domain">
<someList xsi:type="java2:List" soapenc:arrayType="xsd:anyType[]" xmlns:java2="java:language_builtins.util"/>
</itinerary>
</xyzResReq>
</app:someMethod>
</soapenv:Body>
</soapenv:Envelope>
someList is again a complextype in the schema form
<xsd:complexType name="someList">
<xsd:complexContent>
<xsd:extension base="stns:someBaseList">
<xsd:sequence>
<xsd:element maxOccurs="1" name="someElement" type="xsd:boolean" minOccurs="0" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
and someBaseList defined as
<xsd:complexType name="someBaseList">
<xsd:sequence>
<xsd:element maxOccurs="1" nillable="true" name="baseElement" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
How do I do this in savon.
Savon is based on the assumption that most requests (XML) are simple enough to be abstracted as a Hash. In this complex example, I'd suggest two alternatives:
Instead of a Hash, you can use any Ruby object (that's not a Hash) and responds to to_s. So you could create an object (or a hierarchy of objects) with a to_s method constructing the XML via something like Builder and pass it to Savon::SOAP::XML#body=.
class SomeXML
def self.to_s
"<some>xml</some>"
end
end
client.request :some_action do
soap.body = SomeXML
end
You could also use Savon::SOAP::XML#xml, which yields a Builder instance to a given block to construct the XML "on the fly".
client.request :some_action do
soap.xml do |xml|
xml.person { |b| b.name("Jim"); b.phone("555-1234") }
end
end
Hope that helps! Also, please take a look at the new Savon Guide.
I am experiencing a problem with validating an xml file against a schema which was generated by svcutil. For the purpose of this question please see below a snippet of code which contains only a simplified XSD schema and the XML document that I am trying to validate:
Imports System.Xml.Schema
Module Main
Dim errors As Boolean = False
Sub Main()
Try
Dim xsdMarkup As XElement = _
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:tns="http://zen/myservices" targetNamespace="http://zen/myservices">
<xs:element name="Car" type="tns:CarType"/>
<xs:complexType name="CarType">
<xs:sequence>
<xs:element name="Make" minOccurs="1" maxOccurs="1"/>
<xs:element name="Model" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Dim schemas As XmlSchemaSet = New XmlSchemaSet()
schemas.Add("http://zen/myservices", xsdMarkup.CreateReader)
Dim doc1 As XDocument = _
<?xml version='1.0'?>
<Car>
<Makee>content1</Makee>
<Model>content1</Model>
</Car>
Console.WriteLine("Validating doc1")
errors = False
doc1.Validate(schemas, AddressOf XSDErrors)
Console.WriteLine("doc1 {0}", IIf(errors = True, "did not validate", "validated"))
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Console.WriteLine("Hit <ENTER> to exit...")
Console.ReadKey()
End Sub
Private Sub XSDErrors(ByVal o As Object, ByVal e As ValidationEventArgs)
Console.WriteLine("{0}", e.Message)
errors = True
End Sub
End Module
The validation in this particular case should fail (the 'Make' element has been misspelled). Interestingly enough though it passes.
Any ideas what am I missing in this code?
Your help is appreciated.
Zen
All set. I resolved the issue myself. I had accidentally left out the namespaces definition in the XML being validated:
<?xml version='1.0'?>
<Car>
<Makee>content1</Makee>
<Model>content1</Model>
</Car>
should have been:
<?xml version='1.0'?>
<tns:Car xmlns:tns="http://zen/myservices">
<Makee>content1</Makee>
<Model>content1</Model>
</tns:Car>
Validation is failing now as expected.
Zen
while making of POC of LINQ to SQL and entities, i faced a problem stuck in a frozen dead end.
Problem is , am using LINQ to SP and every things was working fine and i made cool methods of editing, adding and deleting. Then some thing click in my mine that "what if i just return two record set from SP". i made a SP and returned two record set from it
SP look like this [Demo]
Create PROCEDURE [dbo].GetUserData
#UserId Bigint
AS
BEGIN
SET NOCOUNT ON;
-- Getting User
select * from [User] where id=#UserId
-- Getting User's role
select * from [Role] where userId=#UserId
end
then i droped that SP in my DBML (Linq to SQL classes) then here i noticed that only schema of one record set was created like this
<?xml version="1.0" encoding="utf-8"?>
<Database Name="MyInventory" Class="MyDBMLDataContext" xmlns="http://schemas.microsoft.com/linqtosql/dbml/2007">
<Connection Mode="AppSettings" ConnectionString="Data Source=MyDatabaseServer\;Initial Catalog=MyInventory;Integrated Security=True" SettingsObjectName="ConsoleApplication16.Properties.Settings" SettingsPropertyName="MyInventoryConnectionString" Provider="System.Data.SqlClient" />
<Function Name="dbo.GetUserData" Method="GetUserData">
<Parameter Name="UserId" Parameter="userId" Type="System.Int64" DbType="BigInt" />
<ElementType Name="GetUserDataResult">
<Column Name="Id" Type="System.Int64" DbType="BigInt NOT NULL" CanBeNull="false" />
<Column Name="Name" Type="System.String" DbType="VarChar(50) NOT NULL" CanBeNull="false" />
<Column Name="Email" Type="System.String" DbType="NVarChar(50)" CanBeNull="true" />
<Column Name="IsDeleted" Type="System.Boolean" DbType="Bit NOT NULL" CanBeNull="false" />
<Column Name="HomePage" Type="System.String" DbType="VarChar(100)" CanBeNull="true" />
</ElementType>
</Function>
</Database>
i can clearly see that only one record set is created of Users records and it is missing Role schema :(.
Can any body tell me what and why is that so?
Thanks
Lura
I have had to deal with something similar in getting multiple data sets from a data base for a website. What we did was create an DatabaseExtensions.cs file to add the queries with multiple data sets.
So in the extensions file we would have something like this
public partial class DataBaseDataContext
{
[ResultType(typeof(FirstResult))]
[ResultType(typeof(SecondResult))]
[Function(Name = "dbo.StoredProc")]
public IMultipleResults StoredProc([global::System.Data.Linq.Mapping.ParameterAttribute(DbType = "Int")] System.Nullable<System.Int> ID)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), ID);
return ((IMultipleResults)(result.ReturnValue));
}
}
public class FirstResult;
public class SecondResult;
Note: I changed some of the names of things in this code to make it easier to read, so it may not work as is.
FirstResult and SecondResult are the result type classes. I would usually copy them from the dbml's accompanying .cs file then rename it. I didn't include their code here because it can be rather long.
DataBaseDataContext dataCon = new DataBaseDataContext();
var results = dataCon.StoredProc(id);
var firstSet = results.GetResult<FirstResult>();
var secondSet = results.GetResult<SecondResult>();
//process data
It is important to get your results out in the same order they come out in your stored procedure. After you have gotten your results out, you can use LINQ or whatever to work with them.
My finding is that if you add a result set to your dbml manually you get the results that you want but LinqToSql doesn't offer you a simple way to have access to them
Here is a path to your results
((System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReaderSession
<System.Data.SqlClient.SqlDataReader>)
(((System.Data.Linq.SqlClient.SqlProvider.ExecuteResult)(result)).session)).buffer
you here have access to your result by index buffer[0] will return the results of your first select statement and buffer[1] returns the result of second select.
probably you can cast this two IEnumerables to typed IEnumerable<GetAllResult> and IEnumerable<GetAllResult1> although I didn't test that.
I build this sample dbml
<Function Name="dbo.GetAll" Method="GetAll">
<ElementType Name="GetAllResult">
<Column Name="ID" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="Tagname" Type="System.String" DbType="NChar(10)" CanBeNull="true" />
</ElementType>
<ElementType Name="GetAllResult1">
<Column Name="Id" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="TagId" Type="System.Int32" DbType="Int" CanBeNull="true" />
<Column Name="Name1" Type="System.String" DbType="NChar(10)" CanBeNull="true" />
</ElementType>
</Function>
and the generated cs file would be like this
[global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.GetAll")]
[global::System.Data.Linq.Mapping.ResultTypeAttribute(typeof(GetAllResult))]
[global::System.Data.Linq.Mapping.ResultTypeAttribute(typeof(GetAllResult1))]
public IMultipleResults GetAll()
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())));
return ((IMultipleResults)(result.ReturnValue));
}
Have you looked code generated for your model? Two resultsets will be here. Mapping can lie.
Ramesh