I am trying to figure out how to change the page with my xslt transformation, by clicking on an element in the table.
I have looked around and couln't find an answer, here is a simple code and I would like to know how to change the page and desplay something:
I don't think it is necessary for you to read the code except for the the final one, the XSLT. I have added the other sections of the code in case they also need some changing.
XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3schools.com"
xmlns="http://www.w3schools.com">
<xs:element name="Table">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element ref="Person"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Person">
<xs:complexType>
<xs:all maxOccurs="1">
<xs:element ref="Name"/>
<xs:element minOccurs="1" ref="Age"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="1" ref="theName"/>
<xs:element maxOccurs="1" ref="Description"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="theName" type="xs:string"/>
<xs:element name="Description" type="xs:string"/>
<xs:element abstract="false" name="Age" type="xs:positiveInteger"/>
</xs:schema>
So I created two elements, theName and the age. Name is composed of the String TheName and the String Description. Age is just a positiveinteger. Now I created the XML file which just chooses two different People:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="try.xsl"?>
<Table xmlns="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3schools.com try.xsd">
<Person>
<Name>
<theName>Thomas</theName>
<Description>He is a nice guy</Description>
</Name>
<Age>10</Age>
</Person>
<Person>
<Name>
<theName>Peter</theName>
<Description>He is good at swimming</Description>
</Name>
<Age>12</Age>
</Person>
</Table>
My transformation now is to make a table with the name of the people in function of there age:
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ws="http://www.w3schools.com"
version="1.0">
<xsl:template match="/">
<html>
<table border="2">
<tr bgcolor="red">
<th>Name</th>
<th>Age</th>
</tr>
<xsl:for-each select="ws:Table/ws:Person">
<tr>
<td><xsl:value-of select="ws:Name/ws:theName"/></td>
<td><xsl:value-of select="ws:Age"/></td>
</tr>
</xsl:for-each>
</table>
This is where I need help, how do I change the page that I am on and go on a page which simply displays the description of the person, I want to do this by clicking on the name of the person. I don't want to open a new window, just change the page.
</html>
</xsl:template>
</xsl:stylesheet>
In your XSLT code, generate HTML that contains a hyperlink to the relevant page. This could be a traditional <a href="..."> hyperlink, or any element with an onclick attribute.
Related
I am looking for someone to assist in solving a seemingly simple problem.
I want to map a node of /fields[x]/message_id to a static node /MessageID0x for 5 entries in a list.
The source node is optional and may not exist.
The schema is below
I am just not seeing the obvious, I hope.
The source is defined as:
<xs:element name="fields">
<xs:complexType>
<xs:sequence>
<xs:element name="tenant_id" type="xs:normalizedString" minOccurs="0"/>
<xs:element name="message_id" type="xs:normalizedString" minOccurs="0"/>
Target is defined as:
<xs:element name="MessageID01" type="xs:normalizedString" minOccurs="0"/>
<xs:element name="MessageID02" type="xs:normalizedString" minOccurs="0"/>
<xs:element name="MessageID03" type="xs:normalizedString" minOccurs="0"/>
<xs:element name="MessageID04" type="xs:normalizedString" minOccurs="0"/>
<xs:element name="MessageID05" type="xs:normalizedString" minOccurs="0"/>
=== FROM ===========
<root>
<ID>2019Nov12_17</ID>
<PingResult>OK</PingResult>
<StartDateTime>2019-11-12T16:16:01</StartDateTime>
<EndDateTime>2019-11-12T17:16:01.771Z</EndDateTime>
<start>0</start>
<numFound>1</numFound>
<fields>
<tenant_id>KOCHIND_AX2</tenant_id>
<message_id>lid://infor.landmark.lmrkmt/15d8f834-7680-541e-0000-001d5dae3e7b</message_id>
</fields>
<fields>
<tenant_id>KOCHIND_AX2</tenant_id>
<message_id>lid://infor.landmark.lmrkmt/0535a86a-7680-1868-0000-07625db833c1</message_id>
</fields>
<fields>
<tenant_id>KOCHIND_AX2</tenant_id>
<message_id>lid://infor.landmark.lmrkmt/0535a86a-7680-1864-0000-03445db849c8</message_id>
</fields>
<fields>
<tenant_id>KOCHIND_AX2</tenant_id>
<message_id>lid://infor.landmark.lmrkmt/0535a86a-7680-1867-0000-01151db125c8</message_id>
</fields>
</root>
TO ===================
<root>
<ID>2019Nov12_17</ID>
<PingResult>OK</PingResult>
<StartDateTime>2019-11-12T16:16:01</StartDateTime>
<EndDateTime>2019-11-12T17:16:01.771Z</EndDateTime>
<start>0</start>
<numFound>1</numFound>
<MessageID01>lid://infor.landmark.lmrkmt/15d8f834-7680-541e-0000-001d5dae3e7b</MessageID01>
<MessageID02>lid://infor.landmark.lmrkmt/0535a86a-7680-1868-0000-07625db833c1</MessageID02>
<MessageID03>lid://infor.landmark.lmrkmt/0535a86a-7680-1868-0000-07625db833c8</MessageID03>
<MessageID04>lid://infor.landmark.lmrkmt/15d8f834-1864—3322-0000-03445db125c8</MessageID04>
<MessageID05>lid://infor.landmark.lmrkmt/15d8f834-7680-1867-0000-01151db125g4</MessageID05>
</root>
I believe the requested result can be achieved rather simply by doing:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="fields">
<xsl:variable name="n">
<xsl:number format="01"/>
</xsl:variable>
<xsl:element name="MessageID{$n}">
<xsl:value-of select="message_id"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
The result of transforming the example input will be:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<root>
<ID>2019Nov12_17</ID>
<PingResult>OK</PingResult>
<StartDateTime>2019-11-12T16:16:01</StartDateTime>
<EndDateTime>2019-11-12T17:16:01.771Z</EndDateTime>
<start>0</start>
<numFound>1</numFound>
<MessageID01>lid://infor.landmark.lmrkmt/15d8f834-7680-541e-0000-001d5dae3e7b</MessageID01>
<MessageID02>lid://infor.landmark.lmrkmt/0535a86a-7680-1868-0000-07625db833c1</MessageID02>
<MessageID03>lid://infor.landmark.lmrkmt/0535a86a-7680-1864-0000-03445db849c8</MessageID03>
<MessageID04>lid://infor.landmark.lmrkmt/0535a86a-7680-1867-0000-01151db125c8</MessageID04>
</root>
which is different from the result you show - nevertheless, I suspect it is the correct one.
Do note that numbering sibling nodes by name is bad practice. It makes subsequent transformations much more difficult. If you need a number (although I don't see why you should), use an attribute.
This question already has answers here:
Why it's not possible to use regex to parse HTML/XML: a formal explanation in layman's terms
(10 answers)
How to read XML using XPath in Java
(8 answers)
Closed 3 years ago.
Would like help to trim the result set elements from my overall XML. The schema of the XML sting is not needed. Would only like the resultSet elements of the xmls.
Below is my xml string:
<NewDataSet>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="NewDataSet">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="resultSet" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="resultSet">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string" minOccurs="0" />
<xs:element name="WAMUserName" type="xs:string" minOccurs="0" />
<xs:element name="AppPoolState" type="xs:string" minOccurs="0" />
<xs:element name="Validation" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<resultSet>
<Name />
<WAMUserName />
<AppPoolState />
<Validation />
</resultSet>
<resultSet>
<Name>W3SVC/APPPOOLS/KTSAAppPool</Name>
<WAMUserName>ST\nzsktsa</WAMUserName>
<AppPoolState>Disabling</AppPoolState>
<Validation>Critical</Validation>
</resultSet>
<resultSet>
<Name>W3SVC/APPPOOLS/KCPSAAppPool</Name>
<WAMUserName>st\nzsOFSA</WAMUserName>
<AppPoolState>Running</AppPoolState>
<Validation>Critical</Validation>
</resultSet>
</NewDataSet>
Would like the below output as part of regex expression.
<resultSet>
<Name />
<WAMUserName />
<AppPoolState />
<Validation />
</resultSet>
<resultSet>
<Name>W3SVC/APPPOOLS/KTSAAppPool</Name>
<WAMUserName>ST\nzsktsa</WAMUserName>
<AppPoolState>Disabling</AppPoolState>
<Validation>Critical</Validation>
</resultSet>
<resultSet>
<Name>W3SVC/APPPOOLS/KCPSAAppPool</Name>
<WAMUserName>st\nzsOFSA</WAMUserName>
<AppPoolState>Running</AppPoolState>
<Validation>Critical</Validation>
</resultSet>
Your code is a mess. But however, you shouldn't use RegEx'es to process XML files. Use an XSLT processor like xsltproc (Linux) or Saxon (Java) or Xerces (Java).
Using an XSLT-1.0 processor, you can extract the resultSet elements easily with the following template.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- identity template -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*" />
</xsl:copy>
</xsl:template>
<xsl:template match="/NewDataSet">
<xsl:apply-templates select="resultSet" />
</xsl:template>
</xsl:stylesheet>
Apply it to your XML file and the result will be
<?xml version="1.0"?>
<resultSet>
<Name/>
<WAMUserName/>
<AppPoolState/>
<Validation/>
</resultSet>
<resultSet>
<Name>W3SVC/APPPOOLS/KTSAAppPool</Name>
<WAMUserName>ST\nzsktsa</WAMUserName>
<AppPoolState>Disabling</AppPoolState>
<Validation>Critical</Validation>
</resultSet>
<resultSet>
<Name>W3SVC/APPPOOLS/KCPSAAppPool</Name>
<WAMUserName>st\nzsOFSA</WAMUserName>
<AppPoolState>Running</AppPoolState>
<Validation>Critical</Validation>
</resultSet>
The command depends on your XSLT processor.
Since I am a beginner in xslt/xsd-programming, I am using XMLSpy to create a xml2xml transformation. For both xml I have got a xsd. Unfortunately, the following code piece is not valid.
<xsl:template match="/">
<table xsi:noNamespaceSchemaLocation="table.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:for-each select="table/body/line">
<row>
</row>
</xsl:for-each>
</table>
</xsl:template>
The error message says that the row element is expected after table.
Details (translated): element <xsl:for-each> was not expected of type {anonymous} of element <table>.
The problem can be solved by removing the reference to the xsd or removing the for-each statement.
However, I cannot figure out what is wrong. To my understanding the for-each-loop should just repeat the <row> tags for each line in the first xml.
Here is part of the xsd of the target.
<xs:element name="table">
<xs:complexType>
<xs:sequence>
<xs:element ref="row" maxOccurs="unbounded"/>
<xs:element ref="Metadata" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
I suspect that Altova is using the presence of the attribute xsi:noNamespaceSchemaLocation="table.xsd" as a signal meaning "please validate this element against the schema in table.xsd"; which is not what you wanted, because of course it's not valid against that schema, as it contains XSLT instructions to create the required elements, rather than containing the required elements themselves.
To work around this, try generating the attribute using xsl:attribute:
<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:attribute name="xsi:noNamespaceSchemaLocation">table.xsd</xsl:attribute>
<xsl:for-each select="table/body/line">
<row/>
</xsl:for-each>
</table>
can anyone give me a paradigm of transforming an xml schema template like
<xs:element name="carareWrap">
<xs:annotation>
<xs:documentation xml:lang="en">The CARARE wrapper element. It wraps CARARE elements.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="unbounded" ref="carare"/>
</xs:sequence>
</xs:complexType>
</xs:element>
to an other xml schema template with xsl?
the other xml schema could be anything you can do.. I just need to have somwthing to start with...
can anyone give me a paradigm of transforming an xml schema template like ... to an other xml schema template?
An XML Schema is just a an XML document with declared namespace uri http://www.w3.org/2001/XMLSchema. Therefore, you can apply XSLT as usual.
For instance, you have a source schema like this:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="carareWrap">
<xs:annotation>
<xs:documentation xml:lang="en">The CARARE wrapper element. It wraps CARARE elements.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="unbounded" ref="carare"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
And (for example) you want to remove the attributes of reference elements only. You can apply the following transform:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="xs:element[#ref]">
<xsl:copy>
<xsl:copy-of select="#ref"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The result will be:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="carareWrap">
<xs:annotation>
<xs:documentation xml:lang="en">The CARARE wrapper element. It wraps CARARE elements.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element ref="carare" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Notice
The needing of the declaration of the namespace of the input document in the XSLT
The usage of the identity transform to copy the input document as is and override the elements as by requirements.
There is nothing special about trating XSD documents. They are just XML.
Since you do not specify what changes you want to make, here is a sample XSLT stylesheet that changes a random detail (the value of minOccurs in this case)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<!-- the identity template copyies everything as-is -->
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" />
</xsl:copy>
</xsl:template>
<!-- ...unless there is a more specific template available -->
<xsl:template match="
xs:element[#name = 'carareWrap']//xs:element[#ref = 'carare' and #minOccurs = 1]/#minOccurs
">
<xsl:attribute name="{name()}">2</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Output
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="carareWrap">
<xs:annotation>
<xs:documentation xml:lang="en">The CARARE wrapper element. It wraps CARARE elements.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="2" maxOccurs="unbounded" ref="carare"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
A few things to notice:
the namespace declaration xmlns:xs="http://www.w3.org/2001/XMLSchema" so the xs prefix is available in the XSLT stylesheet
the use of the identity template copy everything that is not handled otherwise
the use of a complex match expression to pick a specific node
the use of an attribute value template and the name() function to copy the attribute name: name="{name()}"
I'm looking for a way (if it's even possible) of using an XSL transform of an XSD document to remove unused elements. This comes up a lot in my job where a company will define an XSD with absolutely everything in it, but then they will want to create a cut-down version for a single root element within it.
To explain further, I might have an XSD like the following:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="RootElement">
<xs:complexType>
<xs:sequence>
<xs:element ref="ChildElement"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ChildElement"/>
<xs:element name="UnusedElement"/>
</xs:schema>
What I would like to be able to do is to set up an XSL where I provide the starting element (in this case RootElement) and it will copy over all dependent elements but omit the unused ones. In the above example, if I passed in RootElement I'd expect to see RootElement and ChildElement included but UnusedElement omitted.
(When I say "provide the starting element", I'm quite happy to crack open the stylesheet and type xsl:template match="RootElement" where required.)
This would obviously have to be recursive, so would navigate the entire structure defined below the starting element, and any element in that schema that was not used would be discarded.
(Of course, it would be even better if it could do the same in any imported schemas!)
I've searched Google extensively and can't find anything on this - I'm not sure if that means it's not possible or not.
Thanks!
Edit: Actually I probably should clarify and say that I would like to remove unused elements AND types, so it would follow both ref="childElement" and type="someType" links.
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="ptopElementName" select="'RootElement'"/>
<xsl:variable name="vTop" select=
"/*/xs:element[#name=$ptopElementName]"/>
<xsl:variable name="vNames"
select="$vTop/descendant-or-self::*/#name"/>
<xsl:variable name="vRefs"
select="$vTop/descendant-or-self::*/#ref"/>
<xsl:variable name="vTypes"
select="$vTop/descendant-or-self::*/#type"/>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="xs:element">
<xsl:if test=
"#name=$vNames
or
#name=$vRefs
or
ancestor-or-self::*[#name=$ptopElementName]">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
<xsl:template match="xs:complexType|xs:simpleType">
<xsl:if test=
"#name=$vTypes
or
ancestor-or-self::*[#name=$ptopElementName]">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="RootElement">
<xs:complexType>
<xs:sequence>
<xs:element ref="ChildElement"/>
</xs:sequence>
</xs:complexType></xs:element>
<xs:element name="ChildElement"/>
<xs:element name="UnusedElement"/>
</xs:schema>
produces the wanted, corect result:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="RootElement">
<xs:complexType>
<xs:sequence>
<xs:element ref="ChildElement"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ChildElement"/>
</xs:schema>