For example I have XML:
<a>
<b>c</b>
</a>
xsdA.xsd:
<xs:import schemaLocation="xsdB.xsd"/>
<xs:element name="a" xmlns:xsa="http://www.example.org/a" type="xsa:aType"></xs:element>
xsdB.xsd:
<xs:element name="b" xmlns:xsb="http://www.example.org/b" type="xsb:bType"></xs:element>
I want to somehow transform XML into this:
<xsa:a xmlns:xsa="http://www.example.org/a">
<xsb:b xmlns:xsb="http://www.example.org/b">c</xsb:b>
</xsa:a>
I hear that it can be done by JAXB, but is there any way to do this without code generation?
I use Java.
EDIT:
It's just example. I can add namespaces by xslt or manualy in DOM object, but my xsds is 170K size now. And it often changes. I want just replace the xsd and program keep working.
How can i found namespace of element with given localname in bunch of xsd files?
EDIT2:
All localnames seems to be different in my xsds.
As laune suggested, a very basic XSLT that should get you started.
XSLT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsa="http://www.example.org/a"
xmlns:xsb="http://www.example.org/b">
<xsl:output omit-xml-declaration="no" indent="yes" />
<xsl:template match="a">
<xsa:a><xsl:apply-templates select="node() | #*" /></xsa:a>
</xsl:template>
<xsl:template match="b">
<xsb:b><xsl:apply-templates select="node() | #*" /></xsb:b>
</xsl:template>
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Input:
<a>
<b>c</b>
</a>
Output:
<xsa:a xmlns:xsa="http://www.example.org/a" xmlns:xsb="http://www.example.org/b">
<xsb:b>c</xsb:b>
</xsa:a>
Related
My First question is marked as duplicated, but it isn't a duplicate
show XML in HTML with inline stylesheet
I hope this question is not immediatley marked as duplicate, only because one of the moderators has read the first two sentences and've ignored the rest.
The Problem is not to show an XML Structure in HTML, rather to show a full dynamically XML structure, with all tags and occasional colored lines.
The structure and interior fields are full dynamically and every field can be correct or wrong, depending on the xml file like to compare.
So a field is at the first comparison correct, but on another comparison it’s wrong. The fields and structure of XML can vary greatly from one comparison to another.
I’m looking since yesterday for a corresponding and professional solution for this problem.
Background process: comparison different xml files, via soa microservices in java. The comparison is made by org.custommonkey.xmlunit. The Result have to be an html popup, what shows me differences marked by colored lines.
Example Output XUnit Diff Result XPath
/ROOT[1]/MATDETAIL[1]/OUTPUT[1]/GENERAL[1]/CHANGED_BY[1]/text()[1]
Transform the source xml via xslt and the xunit diff result informations.
Example Input XML
<ROOT>
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON/>
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE/>
<CHANGED_BY>NEW USER</CHANGED_BY>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE/>
<LOG_NO/>
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
Example XSL Transformation
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" mode="unescape"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/ROOT[1]/MATDETAIL[1]/OUTPUT[1]/GENERAL[1]/CHANGED_BY[1]">
<xsl:element name = "span">
<xsl:attribute name="style">font-weight:bold; color:red </xsl:attribute>
<xsl:copy>
<xsl:value-of select = "current()" />
</xsl:copy>
<xsl:text><== Expected: dasda</xsl:text>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Example Result of XSL Transformation
<ROOT>
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON/>
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE/>
<span style="font-weight:bold; color:red "><CHANGED_BY>NEW USER</CHANGED_BY><== Expected: ORIGINAL USER</span>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE/>
<LOG_NO/>
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
I’m not able to show this xml structure in html, with (all) tags, correctly AND colored.
Either I’ve get no tags, so there are only the raw data in XML to see, without tags, but the lines are colored.
Or I get the xml structure with all data, but not colored.
I tried to replace the lt and gt chars inside xslt, but failed, or after transformation in java, this result shows very ugly. My colleague has meant that we can not use it in any way.
Because the XML Structur can be every time different and so on fully dynamically, I can not style the xml with css and tag definition.
Unfortunately, alternative implementations are not an option. I have to do this somehow with the means available to me. (Java, XML & XSL, JS, HTML, CSS).
I hope to get good ideas to solute this.
I would like to thank you in advance.
I hope i can solve your issue with following try.
I. Input:
<ROOT baum="baum">
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON/>
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE/>
<CHANGED_BY>NEW USER</CHANGED_BY>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE/>
<LOG_NO/>
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
II. Stylesheet (XSLT 1.0):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="CHANGED_BY">
<span style="color:red;">
<xsl:apply-templates select="." mode="serialize"/>
</span>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates select="." mode="serialize"/>
</xsl:template>
<xsl:template match="#*">
<xsl:apply-templates select="." mode="serialize"/>
</xsl:template>
<xsl:template match="*" mode="serialize">
<xsl:value-of select="concat('<', name())"/>
<xsl:apply-templates select="#*" />
<xsl:choose>
<xsl:when test="node()">
<xsl:text>></xsl:text>
<xsl:apply-templates />
<xsl:value-of select="concat('<', name(), '>')"/>
</xsl:when>
<xsl:otherwise>
<xsl:text> /></xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="#*" mode="serialize">
<xsl:value-of select="concat(' ', name(), '="', ., '"')"/>
</xsl:template>
<xsl:template match="text()" mode="serialize">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
III: Output:
<ROOT baum="baum">
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON />
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE />
<span style="color:red;"><CHANGED_BY>NEW USER</CHANGED_BY></span>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE />
<LOG_NO />
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
IV. Explanation:
Whenever the mode="serialize" is applied, the context is escaped. See example for CHANGED_BY to format with HTML-Tags. The xml structure is fully escaped so the browser shows it like a string instead of tags.
I really hope it solves your problem
I have two .xml files which need to be joined
The first file is Song.xml as the following:
<Songs>
<Song>
<SongID>1</SongID>
<SongName>We dont talk anymore</SongName>
<Author>M-TP</Author>
<UploadBy>admin</UploadBy>
<GerneCode>1</GerneCode>
</Song>
</Songs>
and the Gerne.xml which generate from a schema
<ns2:gernes xmlns="http://www.w3.org/2001/XMLSchema/playlist" xmlns:ns2="https://xml.netbeans.org/schema/genses">
<ns2:gerne>
<GerneCode>1</GerneCode>
<GerneName>Pop</GerneName>
<Image>img-pop.jpg</Image>
</ns2:gerne>
</ns2:gerne>
I want to join these .xml files inside a XSL, to which will add the GerneName for every Song that match the GerneName inside the Gerne.xml.
The result im trying to get should be like this:
<Songs>
<Song>
<SongID>1</SongID>
<SongName>We dont talk anymore</SongName>
<Author>M-TP</Author>
<UploadBy>admin</UploadBy>
<GerneName>Pop</GerneName>
<GerneCode>1</GerneCode>
</Song>
</Songs>
Can anyone help me with this? Any e.g or keywords what should I look up for this problem?
Assuming you are limited to XSLT 1.0, you can do:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:pl="http://www.w3.org/2001/XMLSchema/playlist"
xmlns:ns2="https://xml.netbeans.org/schema/genses"
exclude-result-prefixes="pl ns2">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="lookup-path" select="'Gerne.xml'" />
<xsl:key name="genre" match="ns2:gerne" use="pl:GerneCode" />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="GerneCode">
<xsl:variable name="code" select="." />
<!-- switch context to the other file -->
<xsl:for-each select="document($lookup-path)">
<GerneCode>
<xsl:value-of select="key('genre', $code)/pl:GerneName" />
</GerneCode>
</xsl:for-each>
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
This is assuming you are telling your XSLT processor to process the Song.xml file, and passing the path to the Gerne.xml file as a parameter.
Note that the Gerne.xml document you have posted is not well-formed XML (no </ns2:gernes> closing tag).
BTW, the correct term is "genre" - not "gerne" or "gense".
I have a xml file whose structure looks like this:
<root>
<includes>
<includeFile name="../other/some_xml.xml"/>
</includes>
<itemlist>
<item id="1" >
<selections>
<selection name="one" />
</selections>
</item>
</itemlist>
The xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml" indent="yes" xalan:indent-amount="4" />
<xsl:template match="/">
<xsl:element name="ItemList">
<xsl:if test="root/item">
<xsl:call-template name="templ" />
</xsl:if>
</xsl:element>
</xsl:template>
<xsl:template name="templ">
<xsl:element name="ItemList">
<xsl:for-each select="root/itemlist/item">
<xsl:element name="Item">
<xsl:element name="ItemIdentifier">
<xsl:value-of select="#id" />
</xsl:element>
<xsl:element name="Condition">
<xsl:value-of select="selections/selection[1]/#name" />
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I created one XSLT which i am using to filter out items. The problem is that for every file, i have to check if it contains the includefile tag, which is a relative path pointing to a similar xml, and if it does, i need to collect items from that file also, recursively. For now i transformed the xml using my xslt and then i have to parse the xml to look for includefile tag. This solution doesn't look elegant and i was wondering if all of it could be done via xslt.
The XSLT document function in XSLT 1.0 and in XSLT 2.0 additionally the doc function allow you to pull in further documents, processing is then simply possible with matching templates. So consider to move your XSLT coding style to write matching templates and apply-templates, then you can easily do
<xsl:template match="includes/includeFile">
<xsl:apply-templates select="document(#name)/*"/>
<xsl:template>
and then you simply need to make sure the <xsl:template match="root">...</xsl:template> creates the output you want.
I have a number of XSD schemas with too much documentation in them which makes them hard to read and use, how can I write a program to produce the equivalent XSD files with all the xs:annotation elements (including any xs:appinfo, xs:documentation or other elements they contain) removed whenever they may be found?
You could run each of your files through an XSLT to strip out the unwanted elements:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="xs:annotation" />
</xsl:stylesheet>
As noted by #IanRoberts You only really need to remove the xs:annotation elements and the other two types of elements will be removed along with them.
The input file is as below:
<root>
<node1>
<child_node1>apple mango<sub_node1>water grapes</sub_node1> banana</child_node1>
<child_node2>Cherry mango<sub_node2>Date grapes</sub_node2> Coconut</child_node2>
</node1>
<node2>
<child_node3>banana grapes apple</child_node3>
</node2>
......
</root>
An XSL is required which works for the below requirement.
Requirement:
Need to pass the list of strings and each string from that list has to be checked in this input file for all occurrences of matching text. If found enclose that matched text with a tag say <fruit>.
Example:
For the above input file if I pass list of Strings including: grapes, apple
The Expected output:
<root>
<node1>
<child_node1><fruit>apple</fruit> mango<sub_node1>water <fruit>grapes</fruit></sub_node1> banana</child_node1>
<child_node2>Cherry mango<sub_node2>Date <fruit>grapes</fruit></sub_node2> Coconut</child_node2>
</node1>
<node2>
<child_node3>banana <fruit>grapes</fruit> <fruit>apple</fruit></child_node3>
</node2>
......
</root>
Only the exact matching text needs to be tagged and "<child_node1>apple mango<sub_node1>water grapes</sub_node1> banana</child_node1>" is still valid (The Nodes and its text).
The list of input Strings may be any thing and a generic string matching approach is required which checks with each string in that list.
Any help in this regard is greatly appreciated. Thanks a lot in advance!
i tried something that goes like this:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" method="xml" />
<xsl:strip-space elements="*" />
<xsl:variable name="list">apple mango</xsl:variable>
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" />
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:for-each select="tokenize(., '\s+')">
<xsl:choose>
<xsl:when test=". = tokenize($list, '\s+')">
<fruit><xsl:value-of select="."/></fruit>
</xsl:when>
<xsl:otherwise><xsl:copy-of select="."/></xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>