 |
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead. |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|

April 27th, 2006, 03:03 PM
|
Authorized User
|
|
Join Date: Apr 2006
Posts: 11
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Converting XML to XML (making element mandatory)
Hi,
I have an XML that I am pulling from a webservice. The webservice schema specifies that certain fields have a minoccurs of zero, so obviously the document does not list elements in sequence that have nulls.
This is a problem because my vb.net application that I wrote will immediate call another function that will read the XML and write it to a Sql Server database, and the function crashes bc the document does not contain elements with nulls (because if element #2 has a null in one record, it doesn't write it to the xml so my program thinks element #3 is element #2).
Can you use XSLT to specify either to always write an element no matter what or to write it and put 'null' as a value if it is 'null' is the byte stream from the Web Service?
Thanks in advance.
|

April 27th, 2006, 04:53 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
It's dangerous to talk of "nulls" - there's no such thing in XML. You simply mean an absent element.
In XSLT, if you want to replace absent elements by empty elements, you can write something like this:
<xsl:template match="person">
<name>
<xsl:value-of select="name"/>
</name>
<age>
<xsl:value-of select="age"/>
</age>
etc.
If you want to be more clever you could probably make it table-driven.
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|

April 28th, 2006, 08:17 AM
|
Authorized User
|
|
Join Date: Apr 2006
Posts: 11
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Will this work for elements that may be there some of the time, but won't the rest of the time? The element in question exists in about half of the records.
|

April 28th, 2006, 08:24 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
The code:
<name>
<xsl:value-of select="name"/>
</name>
creates a copy of the input <name> element if there is one (assuming its content is text only), and creates a new empty <name/> element otherwise. That was my reading of your requirements. If the text-only assumption isn't valid, it would be better to do:
<name>
<xsl:apply-templates select="name/node()"/>
</name>
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|

April 28th, 2006, 08:48 AM
|
Authorized User
|
|
Join Date: Apr 2006
Posts: 11
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Ok, I've got a test setup, but I can't get the result I want. It outputs '121', and I did a View Source, and the XML still looks the same. I need the XML to look like this:
This is my desired results:
<testXML>
<name>
<test1>1</test1>
<test2>2</test2>
</name>
<name>
<test1>1</test1>
<test2></test2> //line that needs to appear
</name>
</testXML>
-----------------------
Using this code:
My XSL:
------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="name">
<test1>
<xsl:value-of select="test1"/>
</test1>
<test2>
<xsl:value-of select="test2"/>
</test2>
</xsl:template>
</xsl:stylesheet>
------------------------
My XML:
-----------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<testXML>
<name>
<test1>1</test1>
<test2>2</test2>
</name>
<name>
<test1>1</test1>
</name>
</testXML>
Thanks again for your help!
|

April 28th, 2006, 08:58 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
Sounds as if you're running in the browser. That's the worst way to develop and debug XSLT code - you can't see what you're doing, and the diagnostics are very poor. Either use an XML IDE such as Stylus Studio or XML Spy, or use a plain old text editor and command line (I'm using jEdit and Saxon to develop some complex stylesheets for a client today, and it works fine).
121 is the string value of both the old and the new XML, so this doesn't tell you anything. View Source does what it says - it shows you the source. If you're in IE, there's a plug-in you can get to view the result - but I don't recall the details, as it's not the way I prefer to develop.
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|

April 28th, 2006, 10:01 AM
|
Authorized User
|
|
Join Date: Apr 2006
Posts: 11
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi mhkay,
I opened the xml is XMLSPY and did a View -> TextView and the results are:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<testXML>
<name>
<test1>1</test1>
<test2>2</test2>
</name>
<name>
<test1>1</test1>
</name>
</testXML>
I need them to look like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<testXML>
<name>
<test1>1</test1>
<test2>2</test2>
</name>
<name>
<test1>1</test1>
<test2></test2>
</name>
</testXML>
Am I missing something?
|

April 28th, 2006, 10:22 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
In fact the stylesheet isn't correct, because it isn't outputting a name element. It should be
<xsl:template match="name">
<name>
<test1>
<xsl:value-of select="test1"/>
</test1>
<test2>
<xsl:value-of select="test2"/>
</test2>
</name>
</xsl:template>
But that doesn't account for your output. You seem to be doing something badly wrong (in fact, you seem to be looking at the input).
With the above change, Saxon outputs
<?xml version="1.0" encoding="UTF-8"?>
<name><test1>1</test1><test2>2</test2></name>
<name><test1>1</test1><test2/></name>
(if you want it indented, add <xsl:output indent="yes"/>)
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|

April 28th, 2006, 10:54 AM
|
Authorized User
|
|
Join Date: Apr 2006
Posts: 11
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
That worked!
I just have one last question real quick:
Is there a way to set a default value for elements, if per se they have no value, like the <test2></test2>, could you set it to <test2>null</test2>?
Thanks again for your help. :)
|
|
 |