I'm currently working on a BizTalk project and I encountered a problem which I'm sure should be solvable within a mapping. However, I don't seem to be able to figure out how. Hopefully someone can help me out.
The situation is as follows: in both the source and the target schema, there's a repeating node with roughly the same child elements underneath it (no records or attributes involved). The repeating node within the source has a structure like this:
<fruit>
<item>
<sort>Apple</sort>
<size>5cm</size>
<colour>red</colour>
</item>
<item>
<sort>Pear</sort>
<size>8cm</size>
<colour>green</colour>
</item>
</fruit>
While the repeating node in the target looks more like this:
<FRUIT>
<SORT>Apple</SORT>
<SIZE>5cm</SIZE>
<COLOUR>red</COLOUR>
</FRUIT>
<FRUIT>
<SORT>Pear</SORT>
<SIZE>8cm</SIZE>
<COLOUR>green</COLOUR>
</FRUIT>
What I need the mapping to do, is ensure that if there's any fruit available, there are at least two records 'fruit' available in the target. This should be achieved by adding a generic fruit (just think of some arbitrary pineapple, if you like) to the target, if there's only one fruit available at the source.
As a first step, I tried just adding one more fruit node to the target and failed to do so. I'm pretty confident that if I know how to do this, I can solve the actual problem by combining it with the 'count records' and 'logical equality'(=1) functoids.
So the question boils down to: how do I add a single record to the target inside a mapping?
I've tried several options (and combinations of these), namely:
using a looping functoid over the elements "fruit" or "item", together with some extra value mapping.
directly adding an extra value mapping
adding direct links between "item" or "fruit" and "FRUIT", either with or without looping functoid inbetween.
In most of these cases, either I got a result containing children like
<FRUIT>
<SORT>Pear</SORT>
<SORT>Pineapple</SORT>
<SIZE>8cm</SIZE>
<COLOUR>green</COLOUR>
</FRUIT>
(and a corresponding error since this doesn't satisfy the schema - which doesn't allow for multiple elements SORT), or a whole bunch of pineapples. Neither of which is wished for.
Can anyone help me out?
Unfortunately, there's no easy way to do this in the BizTalk mapper. When you use a looping functoid, it will create an xsl:for-each and will create the destination node exactly the number of times it appears in the source schema.
Since your destination nodes aren't that complex, your best bet is probably to use a Scripting Functoid with inline XSLT, using the following:
<xsl:for-each select="/fruit/item">
<FRUIT>
<SORT><xsl:value-of select="sort"/></SORT>
<SIZE><xsl:value-of select="size"/></SIZE>
<COLOUR><xsl:value-of select="colour"/></COLOUR>
</FRUIT>
<xsl:if test="last() = 1"> <!-- there's only one node here, we want at least two -->
<FRUIT>
<SORT>pineapple</SORT>
<SIZE>8cm</SIZE>
<COLOUR>green</COLOUR>
</FRUIT>
</xsl:if>
</xsl:for-each>
Link the output of that go to the FRUIT node in your destination schema.
Related
BDC model:
My BDC model's entity has a property named Color.
The TypeName is specified as System.String[].
<TypeDescriptor Name="Color" TypeName="System.String[]">
<Properties>
<Property Name="RequiredInForms" Type="System.Boolean">false</Property>
</Properties>
</TypeDescriptor>
Database:
In my database (my BDC content source) I added column values like this one:
;#Blue;#Green;#Yellow;#
Search Schema
I created a new managed property and enabled multiple values (and also refinable - active, queryable, retrievable, safe).
Search Results
Filtering on a specific color via search works.
Example: RsExpAdvWorksProductColor:"blue"
Search Refinement
However I cannot refine on colors.
Adding a refiner on my Managed Property shows up like that:
Color
;#Blue;#Green;#Yellow;#
;#Green;#Yellow;#
;#Red;#Green;#Yellow;#Blue;#Black;#Cyan;#
Obviously the single values are not treated as such - the whole "string" of "special-delimiter" separated values is being shown as a refinment criteria.
Any hints?
Update 2015-03-20: I took a closer look at the built-in multi choice columns. In search results they are being returned as "Value1;#Value2;#" and so on. Basically there is a trailing Red;#Blue;# separator - no leading ;#Red;#Blue;# one. Much to my regret that didn't solve my problem.
Update 2015-03-20: Surprise surprise. It is in fact "working as designed" (like so many things in SharePoint :P). What I am looking for has to be dealt with separately. It behaves exactly the same with built-in multi choice fields so there is nothing wrong with my BDC/Search integration.
Regarding the refiner, have a look at the following links...
http://www.eliostruyf.com/part-6-create-multi-value-search-refiner-control/
https://hyankov.wordpress.com/2014/12/15/sharepoint-2013-refiner-multi-value-contains-instead-of-an-equals/
I try to model my db using this example from solr wiki.
I have a table called item and a table called features with id,featureName,description
here is the updated xml (added featureName)
<dataConfig>
<dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />
<document>
<entity name="item" query="select * from item">
<entity name="feature" query="select description, featureName as features from feature where item_id='${item.ID}'"/>
</entity>
</document>
Now I get two lists in the xml element
<doc>
<arr name="featureName">
<str>number of miles in every direction the universal cataclysm was gathering</str>
<str>All around the Restaurant people and things relaxed and chatted. The</str>
<str>- Do we have... - he put up a hand to hold back the cheers, - Do we</str>
</arr>
<arr name="description">
<str>to a stupefying climax. Glancing at his watch, Max returned to the stage</str>
<str>air was filled with talk of this and that, and with the mingled scents of</str>
<str>have a party here from the Zansellquasure Flamarion Bridge Club from</str>
</arr>
</doc>
But I would like to see the list together (using xml attributes) so that I dont have to join the values.
Is it possible?
I wanted to suggest the ScriptTransformer, it gives you the flexibility to alter the data as needed, but it will not work in your case since it's working at the row level.
You can always define an aggregation function for string concatenation in SQL(example), but you will potentially have performance issues.
If you would use a http/xml data source the solution would have been to use the flatten atribute.
Nevertheless the search functionality will work as expected even if you ended up with multi-valued fields. The down side would be on the client where you will concatenate them before the presentation layer, which is not really a problem if you use some sort of pagination.
Is there a way in an xsd schema to require that an element have another element somewhere as a descendant?
For example, element parent requires a descendant desc. This is valid:
<parent>
<a>
<b>
<desc></desc>
</b>
</a>
</parent>
As is this:
<parent>
<c>
<desc></desc>
</c>
</parent>
but this isn't:
<a>
<parent>
<b/>
</parent>
</a>
The potential child elements for parent are many and complicates, so it would be difficult to enumerate every possible valid configuration.
Something like the key/selector schema elements seems like it would work, where I could provide an xpath expression defining the valid locations for desc element, but all of the examples I've found are aimed at matching up the value of attributes.
No, (almost) all XML Schema validation is shallow, called "local" in the spec. Here's one excerpt that emphasizes type validation as "local" validation.
Element Validated by Type If an
element information item is ·valid·
with respect to a ·type definition· as
per Element Locally Valid (Type)
(§3.3.4), [it is marked as] ·validated·.
The only exception is for the identity constraints like uniqueness and key-references which have a broad scope in an XML document but narrow uses.
I don't know if XSD supports what you are trying to do, but there is a work-around.
You could do complex validations with a two-step process:
First simply use your XSD schema for basic validation
Next use an XSLT which does more complex validations, and outputs the result of that validation
This may not plug in well to whatever framework you are working with, but might work well for (partially) custom code. It also has the advantage (over doing the extra validations in code) that you can publish both documents.
From a quick google search, one effort towards this end is Schematron. It actually foregos XSD entirely, and just uses XSLT. It appears to be a published standard:
http://www.schematron.com/
Let's say I can get XML like this:
<Property Name="Title"/>
<Property Name="Content"/>
<Property Name="Address"/>
<Source properties="Title,Content,Address"/>
How coud I validate the "properties" attribute of "Source", so that any composition of the above listed "Property" items could be checked? (For example: "Title", "Title,Content", all of these concatenations are correct, while "Title, URL" is not correct.)
You can't do that within XML Schema. You can do it with your own higher level of validation based on XSLT, XQuery or Schematron, for example.
xan is right; validating always means, to match a XML file against a given schema. But there is no schema involved here, your problem is instead, to read a data file, and validate later entries against earlier ones (if the box above is supposed to represent one file) or one data file against another data file (if the gap is supposed to be a file separator). Beyond that, a schema defines the structure of elements and attributes and optionally data types (values only, if there is a strict enumeration of valid values). Also no match here, instead you want to verify data against data. Sorry, the tool of a schema mismatches the problem to solve.
Maybe I'm not seeing the forest for the trees, but here it goes:
I'm "designing" an XML document and have so far come up with something like the following:
<element key="root">
<data>...</data>
<elements>
<element key="foo">
<data>...</data>
</element>
<element key="bar">
<data>...</data>
</element>
</elements>
</element>
So it's a simple hierarchical structure. What I want to do now is have references from one element to any other element anywhere in the hierarchy. That would be trivial if each element had a unique ID, but they don't. So far I only plan on guaranteeing that each element's key is unique within its level (much like file names in a directory structure).
In other words, if I had fully qualified keys such as root.foo, guaranteeing referential integrity would be simple. But then I'd be storing redundant information (I already know that foo is a sub element of root, why store that information twice?).
I realize that this is essentially a cosmetic problem. One of the simplest solutions is probably to just auto-assign IDs and be done with it. But this is fairly inelegant (and error-prone unless you have a nice front end for editing the file), so I was hoping for a nicer way to do it.
Is there a way to implement this in XML Schema?
Use <xs:key> and <xs:keyref>
Keys are unique within specified context so they don't need to be globally unique like ID:s <xs:key> contains <xs:selector> element that specify the scope or context of the key (key value/s must be unique across this set) and <xs:field> element that defines the key nodes. A key can have multiple fields in which case their combination must be unique. <xs:key> and <xs:keyref> are used within an <xs:element> declaration.