Is there a way to convert following XML file to element-centric file? Perhaps using an online tool? Without requiring to use VB anything? I need to import this xml to Access, but unable to do so because Access requires element-centric xml.
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="invoices.xsl"?>
<invoices>
<invoice number="25" date="February 28, 2001">
<patient firstname="Jeff" familyname="Smith" SSN="123456789">
<phone type="home" number="123-4567890"/>
<phone number="321-76543321" type="work"/>
<address type="home" line1="123 Street" city="City" state="US" zip="12345"/>
</patient>
<insurance name="Humongous First Medical Insurance" plannumber="12345" planname="The Client Company">
<phone number="098-76543321"/>
<address type="business" line1="321 Street" city="City" state="US" zip="54321"/>
</insurance>
<procedure code="123" name="Cleaning nose" cost="50.00" insurance_estimate="50.00"/>
<procedure code="124" name="Tarot reading of illnesses" cost="150.00" insurance_estimate="120.00"/>
<procedure code="125" name="Just for fun" cost="100.00" insurance_estimate="80.00"/>
</invoice>
<invoice number="27" date="February 28, 2001">
<patient firstname="James" familyname="Smith" SSN="123456765">
<phone type="home" number="123-4562245"/>
<address type="home" line1="432 Street" city="City" state="US" zip="12343"/>
</patient>
<insurance name="Humongous Second Medical Insurance" plannumber="3455" planname="Another Client Company">
<phone number="098-76543321"/>
<address type="business" line1="344 Street" city="Some City" state="US" zip="54323"/>
</insurance>
<procedure code="123" name="Cleaning nose" cost="50.00" insurance_estimate="50.00"/>
<procedure code="124" name="Tarot reading of illnesses" cost="150.00" insurance_estimate="120.00"/>
</invoice>
<invoice number="29" date="February 28, 2001">
<patient firstname="Neil" familyname="Smith" SSN="123456345">
<phone type="home" number="125-4345890"/>
<address type="home" line1="187 Street" city="Lost City" state="US" zip="42145"/>
</patient>
<insurance name="Humongous Third Medical Insurance" plannumber="12345" planname="The Lost City Client Company">
<phone number="198-76345321"/>
<address type="business" line1="342 Street" city="Completely Lost City" state="US" zip="111111-0000"/>
</insurance>
<procedure code="123" name="Cleaning nose" cost="50.00" insurance_estimate="50.00"/>
<procedure code="125" name="Maybe they wouldn't see this line..." cost="100.00" insurance_estimate="80.00"/>
</invoice>
</invoices>
Use following as your invoices.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#*">
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Related
I need to transform a json message to XML. I have created a basic XSL transform script but the resulting XML uses 'map' tags with the json values as 'key' attributes.
Is there a way to have the name values used as tags or do I have to write a second transform XSL to get what I want?
json:
<?xml version="1.0"?>
<data>
{ "Policies":
{
"Policy": {
"PolicyNum": "1234",
"Customer": "Smith"
},
"Policy": {
"PolicyNum": "5678",
"Customer": "Jones"
}
}
}
</data>
xsl:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs math" version="3.0">
<xsl:output indent="yes" omit-xml-declaration="no" />
<xsl:template match="data">
<xsl:copy-of select="json-to-xml(.)"/>
</xsl:template>
</xsl:stylesheet>
resulting XML: (using https://xslttest.appspot.com/)
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://www.w3.org/2005/xpath-functions">
<map key="Policies">
<map key="Policy">
<string key="PolicyNum">1234</string>
<string key="Customer">Smith</string>
</map>
<map key="Policy">
<string key="PolicyNum">5678</string>
<string key="Customer">Jones</string>
</map>
</map>
</map>
The XML I need:
<Policies>
<Policy>
<PolicyNum>1234</PolicyNum>
<Customer>Smith</Customer>
</Policy>
<Policy>
<PolicyNum>5678</PolicyNum>
<Customer>Jones</Customer>
</Policy>
</Policies>
Instead of copying the XML map, push it through templates and transform that map into elements using the #key for the name:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
exclude-result-prefixes="xs math" version="3.0">
<xsl:output indent="yes" omit-xml-declaration="no" />
<xsl:template match="data">
<xsl:apply-templates select="json-to-xml(.)"/>
</xsl:template>
<xsl:template match="fn:*[#key]">
<xsl:element name="{#key}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="fn:map">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Consider the following xml document:
<list>
<group name="pilots">
<person nat="france" gender="female">
<name>mark webber</name>
<address>911 somewhere circle, canberra, australia</address>
<team>redbull</team>
</person>
<person nat="poland">
<name>robert kubica</name>
<address>121 zootle road, cape town, south africa</address>
</person>
</group>
<group name="rugby">
<person nat="france">
<name>thomas castaignede</name>
<adresse>30 rue de la paix, mont-de-marsan, france</adresse>
</person>
<person nat="uk">
<name>shane williams</name>
<address>113 best lane, swansea, wales</address>
<team>ospreys</team>
</person>
<person nat=".."> ... </person>
</group>
<group name="..."> .... </group>
</list>
I need to display the list of names of person using a different color in html (red, blue,etc.) for each nationality. I can't figure out how can i achieve at that purpose.
Here is my attempt:
<xsl:template match="list">
<html>
<body>
<xsl:for-each-group select="group/person" group-by="#nat">
<!--<xsl:variable name="color" select="position()"/>-->
<b><xsl:value-of select="current-grouping-key()"/>: </b>
<p> <xsl:value-of select="current-group()/name" separator=", "/></p>
</xsl:for-each-group>
</body>
</html>
</xsl:template>
So you want e.g. <xsl:param name="colours" as="xs:string*" select="'red', 'blue', 'yellow'"/> as a global parameter and CSS <p style="color: {$colours[$index]}"><xsl:value-of select="current-group()/name" separator=", "/></p> where you have bound <xsl:variable name="index" select="position()"/> inside the for-each-group.
I need to use below xml code file and xsl code file in order to display content on the browser. for some reason, I cannot figure out anything:
The display should look like following, but I cannot figure out what in the world I need to do:
XML file:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="invoices.xsl"?>
<invoices>
<invoice number="25" date="February 28, 2001">
<patient firstname="Jeff" familyname="Smith" SSN="123456789">
<phone type="home" number="123-4567890"/>
<phone number="321-76543321" type="work"/>
<address type="home" line1="123 Street" city="City" state="US" zip="12345"/>
</patient>
<insurance name="Humongous First Medical Insurance" plannumber="12345" planname="The Client Company">
<phone number="098-76543321"/>
<address type="business" line1="321 Street" city="City" state="US" zip="54321"/>
</insurance>
<procedure code="123" name="Cleaning nose" cost="50.00" insurance_estimate="50.00"/>
<procedure code="124" name="Tarot reading of illnesses" cost="150.00" insurance_estimate="120.00"/>
<procedure code="125" name="Just for fun" cost="100.00" insurance_estimate="80.00"/>
</invoice>
<invoice number="27" date="February 28, 2001">
<patient firstname="James" familyname="Smith" SSN="123456765">
<phone type="home" number="123-4562245"/>
<address type="home" line1="432 Street" city="City" state="US" zip="12343"/>
</patient>
<insurance name="Humongous Second Medical Insurance" plannumber="3455" planname="Another Client Company">
<phone number="098-76543321"/>
<address type="business" line1="344 Street" city="Some City" state="US" zip="54323"/>
</insurance>
<procedure code="123" name="Cleaning nose" cost="50.00" insurance_estimate="50.00"/>
<procedure code="124" name="Tarot reading of illnesses" cost="150.00" insurance_estimate="120.00"/>
</invoice>
<invoice number="29" date="February 28, 2001">
<patient firstname="Neil" familyname="Smith" SSN="123456345">
<phone type="home" number="125-4345890"/>
<address type="home" line1="187 Street" city="Lost City" state="US" zip="42145"/>
</patient>
<insurance name="Humongous Third Medical Insurance" plannumber="12345" planname="The Lost City Client Company">
<phone number="198-76345321"/>
<address type="business" line1="342 Street" city="Completely Lost City" state="US" zip="111111-0000"/>
</insurance>
<procedure code="123" name="Cleaning nose" cost="50.00" insurance_estimate="50.00"/>
<procedure code="125" name="Maybe they wouldn't see this line..." cost="100.00" insurance_estimate="80.00"/>
</invoice>
</invoices>
XSL file code:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"/>
<xsl:template match="/">
<HTML>
<BODY bgcolor="#FFFFE0">
<!-- -->
<TABLE border="0" width="100%">
<xsl:for-each select="/invoices/invoice">
<tr>
<td>
<H1>Invoice #
<xsl:value-of select="#number"/>,<BR/>
<xsl:value-of select="#date"/>
</H1>
<TD align="right"><img src="sax_extractData_logo.gif"/>
</td>
</td>
</TR>
</xsl:for-each>
<!-- -->
</TABLE>
<TABLE border="0" width="100%">
<TR valign="top">
<TD>
<xsl:for-each select="/invoice/patient">
To: <xsl:value-of select="#firstname"/><xsl:text> </xsl:text>
<xsl:value-of select="#familyname"/>
<BR/>Account #<xsl:value-of select="#SSN"/>
<BR/>
<xsl:value-of select="address/#line1"/><BR/>
<xsl:if test="address/#line2!=''">
<xsl:value-of select="address/#line2"/><BR/>
</xsl:if>
<xsl:value-of select="address/#city"/>,
<xsl:value-of select="address/#state"/>
<xsl:value-of select="address/#zip"/><BR/>
</xsl:for-each>
</TD>
<TD>
<xsl:for-each select="/invoice/insurance">
Insurance: <xsl:value-of select="#name"/><BR/>
Plan name: <xsl:value-of select="#planname"/><BR/>
Plan #<xsl:value-of select="#plannumber"/><BR/>
<xsl:value-of select="address/#line1"/><BR/>
<xsl:if test="address/#line2!=''">
<xsl:value-of select="address/#line2"/><BR/>
</xsl:if>
<xsl:value-of select="address/#city"/>,
<xsl:value-of select="address/#state"/>
<xsl:value-of select="address/#zip"/><BR/>
<xsl:value-of select="phone/#number"/><BR/>
</xsl:for-each>
</TD>
</TR>
</TABLE>
<P> </P>
<TABLE border="1" width="100%">
<TR>
<TD width="20%">Code</TD>
<TD width="20%">Name</TD>
<TD width="20%">Cost</TD>
<TD width="20%">Insurance estimate</TD>
</TR>
<xsl:for-each select="/invoice/procedure">
<TR>
<TD width="20%"><xsl:value-of select="#code"/></TD>
<TD width="20%"><xsl:value-of select="#name"/></TD>
<TD width="20%"><xsl:value-of select="#cost"/></TD>
<TD width="20%"><xsl:value-of select="#insurance_estimate"/></TD>
</TR>
</xsl:for-each>
</TABLE>
<P> </P>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
In situations like this, rather than write a whole load of XSLT and wonder why it is not working, take a step back, and start with something simple that does work, and build upon that. You have started off all right with selecting the individual invoices, so you could initially just get it to output invoice numbers
<xsl:for-each select="/invoices/invoice">
<H1>
Invoice #<xsl:value-of select="#number"/>
</H1>
<xsl:for-each>
But your problems lie with how you select the patient element. You are doing this....
<xsl:for-each select="/invoice/patient">
But there are two problems. Firstly, this is an absolute expression, not relative to the node you are currently positioned on. The first / represents the top-level document node, so it is looking for root node of invoice in the XML, which does not exist.
Secondly, the loop is in the wrong place anyway. It needs to go inside the xsl:for-each loop for selecting invoice elements, not after it. Then, you can write this....
<xsl:for-each select="/invoices/invoice">
<xsl:for-each select="patient">
To: <xsl:value-of select="#firstname"/> <xsl:value-of select="#familyname"/>
<BR/>
</xsl:for-each>
</xsl:for-each>
Note how the expression is now patient and relative to the current invoice item. You would do similar for the insurance and procedure elements.
Actually, it is better to use xsl:apply-templates here, rather than xsl:for-each, as if nothing else it avoids excess indentation. So, your for-each statement becomes this...
<xsl:apply-templates select="patient" />
And then your have a separate template to output the details
<xsl:template match="patient">
To: <xsl:value-of select="#firstname"/> <xsl:value-of select="#familyname"/>
<BR/>
</xsl:template>
Try this XSLT as a starter. Note, I am not outputting many HTML tables here, or all of the fields, but it should give you idea, so you can build upon it:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"/>
<xsl:template match="/">
<HTML>
<BODY bgcolor="#FFFFE0">
<xsl:apply-templates select="invoices/invoice" />
</BODY>
</HTML>
</xsl:template>
<xsl:template match="invoice">
<H1>
Invoice #<xsl:value-of select="#number"/>
</H1>
<img src="sax_extractData_logo.gif"/>
<br/>
<xsl:apply-templates select="patient" />
<xsl:apply-templates select="insurance" />
<table>
<xsl:apply-templates select="procedure" />
</table>
</xsl:template>
<xsl:template match="patient">
To: <xsl:value-of select="#firstname"/> <xsl:value-of select="#familyname"/>
<BR/>
</xsl:template>
<xsl:template match="insurance">
Insurance: <xsl:value-of select="#name"/>
<BR/>
</xsl:template>
<xsl:template match="procedure">
<tr>
<td><xsl:value-of select="#code"/></td>
<td><xsl:value-of select="#name"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
How to write xsl in the body of products.xsl that will get product name and condition with quantity > 10
products.xml:
<?xml version="1.0" encoding="iso-8859-1"?>
<products>
<product>
<name>soaps</name>
<quantity>10</quantity>
<condition>ready</condition>
</product>
<product>
<name>soaps</name>
<quantity>15</quantity>
<condition>ready</condition>
</product>
<product>
<name>soaps</name>
<quantity>20</quantity>
<condition>ready</condition>
</product>
</products>
products.xsl
<?xml version="1.0"?><!-- DWXMLSource="products.xml" -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE> products</TITLE>
</HEAD>
<BODY>
products quantity greater than 10 : <BR/>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
This should do the trick:
<xsl:for-each select="/products/product">
<xsl:if test="quantity > 10">
<xsl:value-of select="name" />: <xsl:value-of select="condition" /> <br/>
</xsl:if>
</xsl:for-each>
This should work: (if provided with a well-formed XML – see comment on question)
<BODY> products quantity greater than 10 : <BR/>
<xsl:apply-templates select="//product[quantity > 10]"/>
</BODY>
Combined with e.g. this template:
<xsl:template match="product">
<P>
<xsl:value-of select="name"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="condition"/>
</P>
</xsl:template>
Just customize per your needs…
This transformation (no <xsl:for-each> and no conditional instructions):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="product[quantity > 10]">
<p>
Product: <xsl:value-of select="name"/>
contition: <xsl:value-of select="condition"/>
quantity: <xsl:value-of select="quantity"/>
</p>
</xsl:template>
<xsl:template match="product"/>
</xsl:stylesheet>
when applied on the provided XML document:
<products>
<product>
<name>soaps</name>
<quantity>10</quantity>
<condition>ready</condition>
</product>
<product>
<name>soaps</name>
<quantity>15</quantity>
<condition>ready</condition>
</product>
<product>
<name>soaps</name>
<quantity>20</quantity>
<condition>ready</condition>
</product>
</products>
produces the wanted result:
<p>
Product: soaps
contition: ready
quantity: 15</p>
<p>
Product: soaps
contition: ready
quantity: 20</p>
How to write xsl in the body of products.xsl that will get product name and condition with quantity > 10
products.xml:
<?xml version="1.0" encoding="iso-8859-1"?>
<products>
<product>
<name>soaps</name>
<quantity>10</quantity>
<condition>ready</condition>
</product>
<product>
<name>soaps</name>
<quantity>15</quantity>
<condition>ready</condition>
</product>
<product>
<name>soaps</name>
<quantity>20</quantity>
<condition>ready</condition>
</product>
</products>
products.xsl
<?xml version="1.0"?><!-- DWXMLSource="products.xml" -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE> products</TITLE>
</HEAD>
<BODY>
products quantity greater than 10 : <BR/>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
This should do the trick:
<xsl:for-each select="/products/product">
<xsl:if test="quantity > 10">
<xsl:value-of select="name" />: <xsl:value-of select="condition" /> <br/>
</xsl:if>
</xsl:for-each>
This should work: (if provided with a well-formed XML – see comment on question)
<BODY> products quantity greater than 10 : <BR/>
<xsl:apply-templates select="//product[quantity > 10]"/>
</BODY>
Combined with e.g. this template:
<xsl:template match="product">
<P>
<xsl:value-of select="name"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="condition"/>
</P>
</xsl:template>
Just customize per your needs…
This transformation (no <xsl:for-each> and no conditional instructions):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="product[quantity > 10]">
<p>
Product: <xsl:value-of select="name"/>
contition: <xsl:value-of select="condition"/>
quantity: <xsl:value-of select="quantity"/>
</p>
</xsl:template>
<xsl:template match="product"/>
</xsl:stylesheet>
when applied on the provided XML document:
<products>
<product>
<name>soaps</name>
<quantity>10</quantity>
<condition>ready</condition>
</product>
<product>
<name>soaps</name>
<quantity>15</quantity>
<condition>ready</condition>
</product>
<product>
<name>soaps</name>
<quantity>20</quantity>
<condition>ready</condition>
</product>
</products>
produces the wanted result:
<p>
Product: soaps
contition: ready
quantity: 15</p>
<p>
Product: soaps
contition: ready
quantity: 20</p>