Jump to content

Add new namespaces to output


T-Otte
 Share

Recommended Posts

Hi,I read a lot of problems and solutions for namespaces today, but after hours and hours i still wasn't able to figure out my own problem. Maybe i didn't understand the namespace handling in xslt quite right yet, so please bare with me if this is an obvious question.Except the name attribute which can have different values my output needs to look exactly like this:

<?xml version="1.0" encoding="UTF-8"?><package name="com.sample"		 xmlns="http://drools.org/drools-5.0"		 xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"		 xs:schemaLocation="http://drools.org/drools-5.0 drools.org/drools-4.0.xsd">

I am doing multiple xslt transformations to my source documents. In the first one the "package" element is created, then in another one the name attribute is added. As shown in this snippet:

	<xsl:template match="package">		<xsl:copy>			<xsl:attribute name="name">				<xsl:value-of select="$names/package/@name" disable-output-escaping="yes"></xsl:value-of>			</xsl:attribute>

I tried to add the declerations by putting them after the value of "name", but then the '"' were escaped, despite using output-escaping="yes". The escaping also happens if i put the declarations inside xsl:text and/or CDATA.Another approach i tried was to add another xslt transformation afterwards with the following declaration:

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://drools.org/drools-5.0" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://drools.org/drools-5.0 drools-4.0.xsd">

Besides the declaration it contains an identity template to copy everything. However i only get the xmlns="http://drools.org/drools-5.0" but not the rest of the namespace declarations.I also tried to add the namespaces using xsl:attribute or xsl:namespace, but both xalan and saxon told me that it is forbidden to create an attribute named "xmlns".Thank you for your help!Best regardsTobias

Link to comment
Share on other sites

You need something like this:

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:temp="http://drools.org/drools-5.0" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"	version="1.0">	<xsl:template match="/temp:package">		<xsl:copy>			<xsl:copy-of select="@xmlns|@xs:schemaLocation"/>			<xsl:attribute name="name">				..			</xsl:attribute>		</xsl:copy>	</xsl:template></xsl:stylesheet>

Cheers, John Bampton.

Link to comment
Share on other sites

Thank you for your answer John. Unfortuantely it doesn't seem to change anything.Maybe i should have shown how my document looks before the second transformation.Before the second xslt it looks like this:

<?xml version="1.0" encoding="UTF-8"?><package>   <rule>	  <lhs>...

Then after i apply the second xslt, that is shown in the first post, i get:

</package><?xml version="1.0" encoding="UTF-8"?><package name="rules">   <rule name="1">	  <lhs>...

Link to comment
Share on other sites

Thanks for your reply. The documents are quite long, so i will only focus on the relevant parts.My input is a pmml decision tree model. My output is a number of rules in the drools xml language. These rules need to be named. Since i can't know beforehand how many rules the decision tree contains and what they do, the user can't name them. So the idea is to do a first transformation that transforms the tree into rules and then a second transformation that reads the appropriate names from another xml file and integrates those names into the output of the first transformation.The resulting xml document is then translated into the drools rule language (DRL)(not an xml format) by using the API from Drools. The XML-->DRL translator only accepts my files if they start like this:

<?xml version="1.0" encoding="UTF-8"?><package name="com.sample"		 xmlns="http://drools.org/drools-5.0"		 xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"		 xs:schemaLocation="http://drools.org/drools-5.0 drools.org/drools-4.0.xsd">

So step by step:Step 1: Decison Tree is transformed to rule using the following xslt. Here the "package" element is created and other templates are used to write other elements into the package.

?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="2.0"	xmlns:xsl="http://www.w3.org/1999/XSL/Transform">	<xsl:output method="xml" version="1.0" encoding="UTF-8"		indent="yes">	</xsl:output>	<xsl:template match="/">		<xsl:element name="package">			<xsl:apply-templates select="//Node[count(descendant::Node)=0]"></xsl:apply-templates>		</xsl:element>	</xsl:template>	<xsl:template match="//Node[count(descendant::Node)=0]">...

This creates the following output:

<?xml version="1.0" encoding="UTF-8"?><package>   <rule>	  <lhs>		 <pattern>			<field-constraint field-name="brand">			   <literal-restriction evaluator="==" value="Porsche"/>			</field-constraint>			<field-constraint field-name="age">			   <literal-restriction evaluator="<=" value="24.0"/>			</field-constraint>		 </pattern>	  </lhs>...

Step2: A second xml document that contains the names is imported and where appropriate name attributes are added to the result tree from before. The name document looks like this:

<?xml version="1.0" encoding="UTF-8"?><names><package name="car insurance rules"></package><imports></imports><objects><object name="Ownership"><fields><field name="hp" attribute="car.hp"></field><field name="brand" attribute="car.brand"></field>

The second transformation with your suggestions:

<?xml version="1.0" encoding="utf-8"?><xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:temp="http://drools.org/drools-5.0" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://drools.org/drools-5.0 drools-4.0.xsd">	<xsl:output method="xml" version="1.0" encoding="UTF-8"		indent="yes"/>	<!-- Document that contains the names -->	<xsl:variable name="names"		select="document('KNIMECarInsuranceToDroolsObjects.xml')/names" />	<!-- copy everything -->	<xsl:template match="@* | node()">		<xsl:copy>			<xsl:apply-templates select="@* | node()" />		</xsl:copy>	</xsl:template>	<!-- Exception for the package name attribute -->	<xsl:template match="/temp:package">		<xsl:copy>			<xsl:copy-of select="@xmlns|@xs:schemaLocation"/>			<xsl:attribute name="name">				<xsl:value-of select="$names/package/@name" disable-output-escaping="yes"></xsl:value-of>			</xsl:attribute>			<!-- Import statements -->			<xsl:for-each select="$names/imports/import">				<xsl:variable name="importposition">					<xsl:number />				</xsl:variable>

The result:

<?xml version="1.0" encoding="UTF-8"?><package>   <rule name="1">	  <lhs>		 <pattern object-type="Ownership">			<field-constraint field-name="car.brand">			   <literal-restriction evaluator="==" value="Porsche"/>

So it seems like /temp:package doesn't yield any results, hence package doesn't get a name or the attributes.Did i apply your solution wrong?

Link to comment
Share on other sites

If your XML input contains elements like the "package" element in no namespace and you want to create elements in a certain namespace like http://drools.org/drools-5.0 then you can do that as follows:

<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="2.0"  xmlns="http://drools.org/drools-5.0">  <xsl:template match="*">	<xsl:element name="{local-name()}">	  <xsl:apply-templates select="@* | node()"/>	</xsl:element>  </xsl:template></xsl:stylesheet>

Link to comment
Share on other sites

If your XML input contains elements like the "package" element in no namespace and you want to create elements in a certain namespace like http://drools.org/drools-5.0 then you can do that as follows:
<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="2.0"  xmlns="http://drools.org/drools-5.0">  <xsl:template match="*">	<xsl:element name="{local-name()}">	  <xsl:apply-templates select="@* | node()"/>	</xsl:element>  </xsl:template></xsl:stylesheet>

Thanks for your help Martin. So i would add that as an additional transformation right?So what i did to integrate your solution:Revert to my original translation without Johns translation. Then i get the following output:
<?xml version="1.0" encoding="UTF-8"?><package name="car insurance rules">   <rule name="1">	  <lhs>		 <pattern object-type="Ownership">			<field-constraint field-name="car.brand">...

Now i applied your xslt, but added the xmlns:xs and xs:schemaLocation

<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="2.0"  xmlns="http://drools.org/drools-5.0"  xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"   xs:schemaLocation="http://drools.org/drools-5.0 drools-4.0.xsd">  <xsl:template match="*">	<xsl:element name="{local-name()}">	  <xsl:apply-templates select="@* | node()"/>	</xsl:element>  </xsl:template></xsl:stylesheet>

The result is:

<?xml version="1.0" encoding="UTF-8"?><package xmlns="http://drools.org/drools-5.0">car insurance rules   <rule>1	  <lhs>		 <pattern>Ownership			<field-constraint>car.brand			   <literal-restriction>==Porsche</literal-restriction>

So the name attribut got lost and i only got the first part of the declaration that i need. Do you have a suggestion what went wrong?

Link to comment
Share on other sites

My suggestion is indeed intended as a separate transformation step, but not as that is necessary, but rather as you seemed to want to do it that way.As for the name or other attributes missing, you would need to add a template of course copying attributes e.g.

<xsl:template match="@*><xsl:copy/></xsl:template>

As for the schemaLocation, for that we need an additional template e.g.

<xsl:temlate match="/*">  <xsl:element name="{local-name()}">	<xsl:attribute name="xs:schemaLocation">http://drools.org/drools-5.0 drools-4.0.xsd</xsl:attribute>	<xsl:apply-templates select="@* | node()"/>  </xsl:element></xsl:template>

Put that template after the one with match="*". And keep the stuff you have on the xsl: stylesheet element.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...