Is it possible to inject a namespace into an XSLT document so that (for instance) the value of a string is used to specify a namespace? I know that it is similarly possible to declare attributes and elements (for instance) using the <xsl:attribute/> and <xsl:element/> constructs, respectively. Is there a similar construct for namespaces?
The reason why I ask for this is that I want to construct an XSLT transformation for constructing an XML request used across a number of vendors that accepts the same XML structure (except that they apply different namespaces).
I use the Saxon XSLT processor.
Easily done in XSLT 2.0 using xsl:namespace.
If you really need to do it in XSLT 1.0 (why?), there's a tortuous workaround:
<xsl:variable name="temp">
<xsl:element name="{$prefix}:dummy" namespace="{$uri}"/>
</xsl:variable>
<xsl:copy-of select="exsl:node-set($temp//*/namespace::*)"/>
In XSLT 2 and later there is xsl:namespace (https://www.w3.org/TR/xslt-30/#creating-namespace-nodes) of course, I am not sure however it will help to deal with input from different namespaces as, like xsl:element, it creates result nodes.
And don't forget that both xsl:element and xsl:attribute allow you to construct result nodes in a different namespace using the namespace attribute.
There is *:foo to select or match foo elements in any namespace.
Related
Recently I've encountered a service that returns its results in XML, in sort of following fashion
<event>
<event-header>
...
</event-header>
<event-body>
...
</event-body>
</event>
Notice that the document does not have a namespace definition. As a result, there is no "official" schema that I can use.
I have written a schema definition that I can use to generate classes that are usable in code to interact with equivalent elements in the document. From observation I can tell that the document format does not change (field order remains the same, fields are not introduced or go away). But question stands, can I still deserialize the provided document using my schema? As far as I know, schemas must define a namespace, and in theory the documents above and below
<event xmlns="http://saltyjuice.lt/dragas/event-service/1.0/event-schema.xsd">
<event-header>
...
</event-header>
<event-body>
...
</event-body>
</event>
are not equivalent.
For reference, I'm using stax and woodstox 6 as implementation.
You can have a schema for a no-namespace document, I don't know why you thought otherwise. It's not ideal, because a namespace can guide people to the right schema. But it's allowed. Anyway, even with a namespace, it's quite possible to have several schemas for the same namespace (usually, versions and variants).
I am setting the parameter like this:
Document doc_23 = createDocument(doc_bytes);
XPathExpression xpe = XPathFactory.newInstance().newXPath().compile("/");
transformer.setParameter("document23",xpe.evaluate(doc_23, XPathConstants.NODESET));
I also tried this:
transformer.setParameter("document23",new StreamSource(new StringReader(xml_text)));
In my xslt i am getting the variable like this:
<xsl:variable name="document23" select="/.."></xsl:variable>
And try to use it:
<xsl:for-each select="$document23//Product">
<xsl:message>Test<xsl:value-of select="generalDetails/productCode"/></xsl:message>
</xsl:for-each>
But i dont work (the for-each never get enterd).
The document have the elements speciffied beacasue using 'document(document23.xml)//Product' does work.
Thanks for the help.
You're using the DOM and JAXP APIs, which isn't an ideal way of using Saxon: the DOM is very slow with Saxon, and the JAXP XPath API is very weakly-typed so you need to have the interface specification and the Saxon-specific details both to hand in order to use it successfully. So my first recommendation would be, if you're committed to Saxon then you would be better off using the s9api API in preference.
In fact I don't understand why you are using XPath interfaces at all. You seem to be trying to run the XPath expression "/", which returns whatever you supply as the input. That's completely pointless.
If you do want to use the JAXP transformation API (and therefore setParameter()), the kind of things you can supply are described here:
http://www.saxonica.com/documentation/index.html#!using-xsl/embedding/jaxp-transformation
In particular see the paragraph that starts "The types of object that can be supplied as stylesheet parameters ..." This links to the "Extensibility" section, which tells you
"If the [...] value is an instance of javax.xml.transform.Source (other than a NodeInfo), a tree is built from the specified Source object, and the root node of this tree is returned as the result of the function."
So you can supply a StreamSource or a DOMSource to the setParameter() method as in your example.
If the path expression in an xsl:for-each appears to be selecting nothing, use xsl:message or xsl:copy-of to display the document you are trying to select into; this will often give you a clue what is wrong.
I see one problem, mainly that you have used <xsl:variable name="document23" select="/.."></xsl:variable>, if you want to define an external parameter then you need to use <xsl:param name="document23" select="/.."/>, not xsl:variable.
I have some persisted XML that was generated by XStream, and looks like:
<CalculationDefinition>
<id>47</id>
<version>3</version>
<name>RHO error (pts)</name>
<expression class="com.us.provider.expression.AbsoluteValue">
....
</expression>
</CalculationDefinition>
I want to persist this content differently now, and want to tell XStream to simply ignore the expression element entirely. There's many links around that talk about how to do this with a MapperWrapper (eg XStream JIRA) but as far I can tell it doesn't work for an element that has a 'class' attribute.
This can be worked around by leaving an 'expression' field in the CalculationDefinition, but I'd rather not have to keep it there now that it's not used in code.
You could filter the incoming XML using XSL and removing the expression nodes, before passing it to XStream.
We have an XML which needs to be validated against an XSD. The XML is being generated by XSTREAM. and We are using jaxp api's to validate the XML against the respective XSD. Unfortunately, currently our test case fail as the generated XML has elements/Tags in different order/sequence than the XSD.
Is it possible to ignore the order of elements in generated XML while validating it against XSD?
Thanks for the help in advance.
What you are asking for is a way to say "validate some of the XSD and ignore other parts". I don't think that can be done.
One possible solution would be to modify the schema so that instead of using a <sequence> for those elements (which requires that the elements be in a particular order) you can use <all>, which allows the elements to be in any order.
The point of a schema is to impose certain structure and requirements on an XML document. You can't just say "eh, I don't like that particular part of the schema, ignore it" as then the document doesn't conform to the schema anymore.
Let's say I have a doc.xml and corresponding doc.xsd. I use xpath to retrieve some nodes, so I get a list of org.w3c.dom.Node. How can I get type of each node from schema, eg. xs:integer, xs:string etc ?
Some solution would be to parse schema with xpath query "//NodeName[#type]" using node.getNodeName() as NodeName, but that's not perfect. I can't be sure that schema is elegant - what if NodeName exists in many places in schema and has not been extracted as a separate type?
So generally I am looking for a reliable solution to get the node type for ANY valid xml & xsd.
You should consider using JAXB. It will create Java classes for you based on the schema type. Then your XML docs are read into those classes, which are typed according to how you defined your XSD. Therefore xsd:int maps to java int(or Integer wrapper class, I can't recall), etc.
Cast your DOM Elements to TypeInfo: from there, you can access the type information you're looking for.
Unfortunately types as defined in an XML Schema (XSD) or Document Type Definition (DTD) are not directly tied to XML document they validate. The elements and attributes in an XML document do not inherently have a type they are just text. Think of an XSD as a script that validates an XML document rather than a set of type annotations for elements and attributes.
The XML specification does not define types as you are thinking of them here. Even Document Type Definitions (DTD) which can be embedded inside XML documents more about the structure of the document not the type of the data contained in elements and attributes.
The type system described in XML Schema is an optional layer of validation that can be applied to XML documents. Since this validation optional the standard XML APIs do not provide a way to bind the validation rules in an XSD to the actual attributes and elements.
I think it would be possible for an XML API to provide a mechanism to bind an XSD to a specific XML document, but I am not aware of an XML parser that does this. One reason why this is not so easy is that the type system that is defined in XML Schema is much richer than is supported in most mainstream programming languages. In your example you may only be interested in xs:integer, xs:string and the like but in XML Schema you can create types that specify ranges, patterns and other things that are just not possible with data types in most programming languages. To represent this complex type system in Java or any programming language would have to be done through a fairly complex API. The the question becomes it is really worth it? I would say probably not.
As per David Ds answer, slightly cleaner, call getSchemaTypeInfo() on an element or attribute