473,473 Members | 1,947 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

another XSLT problem

Hello,

I'm trying to solve an XSLT problem, and I'm hoping someone can give a
little guidance. I am transforming XML to HTML.

Here's an example of the XML file I'm dealing with, greatly simplified:

-----------------
<root>

<object name="a">
<item name="a1">Text here</item>
<item name="readonlya2">Text here</item>
<item name="a3">Text here</item>
<item name="readonlya4">Text here</item>
<item name="a5">Text here</item>
</object>

<object name="b">
<item name="b1">Text here</item>
<item name="b2">Text here</item>
<item name="b3">Text here</item>
<item name="b4">Text here</item>
<item name="b5">Text here</item>
</object>

</root>
----------------------

An <object> element contains several <item> elements. I handle each
<object> separately.

If an <object> contains no read-only <item> elements (identified by
name="readonly.."), I want to print "None" in the HTML output.

If there is one or more read-only <item> in an <object>, I will display
those read-only <item> elements in an HTML table.

It seemed simple, but I have tried using a key, and a recursive
template, and anything else I could think of. I can't find out if there
are any read-only <item>s before putting something in the result tree.
If I could set a global variable from within a template, then it would
be easy to check that variable to tell whether or not to create a table
or print "None." But that is apparently not possible.

Have I missed something?

Thanks!
Mark

Aug 24 '05 #1
11 1535

"ned786" <n7**@earthlink.net> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Hello,

I'm trying to solve an XSLT problem, and I'm hoping someone can give a
little guidance. I am transforming XML to HTML.

Here's an example of the XML file I'm dealing with, greatly simplified:

-----------------
<root>

<object name="a">
<item name="a1">Text here</item>
<item name="readonlya2">Text here</item>
<item name="a3">Text here</item>
<item name="readonlya4">Text here</item>
<item name="a5">Text here</item>
</object>

<object name="b">
<item name="b1">Text here</item>
<item name="b2">Text here</item>
<item name="b3">Text here</item>
<item name="b4">Text here</item>
<item name="b5">Text here</item>
</object>

</root>
----------------------

An <object> element contains several <item> elements. I handle each
<object> separately.

If an <object> contains no read-only <item> elements (identified by
name="readonly.."), I want to print "None" in the HTML output.

If there is one or more read-only <item> in an <object>, I will display
those read-only <item> elements in an HTML table.

It seemed simple, but I have tried using a key, and a recursive
template, and anything else I could think of. I can't find out if there
are any read-only <item>s before putting something in the result tree.
If I could set a global variable from within a template, then it would
be easy to check that variable to tell whether or not to create a table
or print "None." But that is apparently not possible.


Use:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>

<xsl:template match="object">
<xsl:choose>
<xsl:when test="not(*[starts-with(@name,'readonly')])">
None
</xsl:when>
<xsl:otherwise>
<table>
<xsl:for-each select="*[starts-with(@name,'readonly')]">
<tr><td><xsl:value-of select="@name"/></td></tr>
</xsl:for-each>
</table>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

Aug 24 '05 #2
Thank you! I will check this out. It worked on my simplified XML file,
I will see what I get on the real thing.

I didn't know you could put a predicate [...] on an asterisk (*), as in
*[starts-with...etc].

Mark

Aug 24 '05 #3
ned786 wrote:
Hello,

I'm trying to solve an XSLT problem, and I'm hoping someone can give a
little guidance. I am transforming XML to HTML.

Here's an example of the XML file I'm dealing with, greatly simplified:

-----------------
<root>

<object name="a">
<item name="a1">Text here</item>
<item name="readonlya2">Text here</item>
<item name="a3">Text here</item>
<item name="readonlya4">Text here</item>
<item name="a5">Text here</item>
</object>

<object name="b">
<item name="b1">Text here</item>
<item name="b2">Text here</item>
<item name="b3">Text here</item>
<item name="b4">Text here</item>
<item name="b5">Text here</item>
</object>

</root>
----------------------

An <object> element contains several <item> elements. I handle each
<object> separately.

If an <object> contains no read-only <item> elements (identified by
name="readonly.."), I want to print "None" in the HTML output.

If there is one or more read-only <item> in an <object>, I will display
those read-only <item> elements in an HTML table.

It seemed simple, but I have tried using a key, and a recursive
template, and anything else I could think of. I can't find out if there
are any read-only <item>s before putting something in the result tree.
<xsl:template match="object">
<xsl:variable name="roi"
select="count(item[starts-with(@name,'readonly')])"/>
<xsl:choose>
<xsl:when test="$roi=0">
<xsl:text>None</xsl:text>
</xsl:when>
<xsl:otherwise>
...do some table stuff...
</xsl:otherwise>
</xsl:choose>
</xsl:template>
If I could set a global variable from within a template, then it would
be easy to check that variable to tell whether or not to create a table
or print "None." But that is apparently not possible.

Have I missed something?


Set a variable. Test it. Keep it simple :-)
The trick is getting to grips with what XPath can do.

///Peter
Aug 24 '05 #4
ned786 wrote:
I didn't know you could put a predicate [...] on an asterisk (*), as in
*[starts-with...etc].


That's not the beginning of the predicate; it's the end of the selection
path (and in this case all of the selection path) before it.

Soren
Aug 24 '05 #5
Peter,

Wow, that fixes the problem, and it's elegant to boot! Thanks!

Here's the way I had to modify it for my actual XML files:

<xsl:variable name="ro"
select="count(items/item[starts-with(@iname,'dr') or
starts-with(@iname,'hr') or
starts-with(@iname,'usr') or
starts-with(@iname,'szr') or
starts-with(@iname,'ulr') or
starts-with(@iname,'ipr') or
starts-with(@iname,'br') or
starts-with(@iname,'ucr')])"/>
<xsl:choose>
<xsl:when test="$ro=0" >
<p>No read-only items.</p>
</xsl:when>
<xsl:otherwise>
<table>... etc.
</table>
</xsl:otherwise>
</xsl:choose>

As you can see, there are actually 8 different strings that indicate
"read-only" (dr, hr, etc.). Now I am trying to figure out how to "NOT"
that count() function above so I can do the same thing for the
remaining writable items: Print "None" if there are none, and put them
in a table if they exist. The following two have failed:

<xsl:variable name="ro"
select="count(items/item[not(starts-with(@iname,'dr')) or
not(starts-with(@iname,'hr')) or
... ])"/>

<xsl:variable name="ro"
select="count(items/item[@iname != starts-with(@iname,'dr') or
@iname != starts-with(@iname,'hr') or

... ])"/>
I'm trying to find the <item> elements that do not have the read-only
indication. If I can get this to work (find NOT read-only), it will
save work. Do you have any further enlightenment?

Regards,
Mark

Aug 26 '05 #6
ned786 wrote:
Peter,

Wow, that fixes the problem, and it's elegant to boot! Thanks!

Here's the way I had to modify it for my actual XML files:

<xsl:variable name="ro"
select="count(items/item[starts-with(@iname,'dr') or
starts-with(@iname,'hr') or
starts-with(@iname,'usr') or
starts-with(@iname,'szr') or
starts-with(@iname,'ulr') or
starts-with(@iname,'ipr') or
starts-with(@iname,'br') or
starts-with(@iname,'ucr')])"/>
<xsl:choose>
<xsl:when test="$ro=0" >
<p>No read-only items.</p>
</xsl:when>
<xsl:otherwise>
<table>... etc.
</table>
</xsl:otherwise>
</xsl:choose>

As you can see, there are actually 8 different strings that indicate
"read-only" (dr, hr, etc.). Now I am trying to figure out how to "NOT"
that count() function above so I can do the same thing for the
remaining writable items: Print "None" if there are none, and put them
in a table if they exist. The following two have failed:

<xsl:variable name="ro"
select="count(items/item[not(starts-with(@iname,'dr')) or
not(starts-with(@iname,'hr')) or
... ])"/>
The above should work if you change all "or" to "and".
You're negating the condition, so you must negate the conjunction too.

///Peter
<xsl:variable name="ro"
select="count(items/item[@iname != starts-with(@iname,'dr') or
@iname != starts-with(@iname,'hr') or

... ])"/>
I'm trying to find the <item> elements that do not have the read-only
indication. If I can get this to work (find NOT read-only), it will
save work. Do you have any further enlightenment?

Regards,
Mark


Aug 26 '05 #7
Your last suggestion also works, Peter, and you are my hero. Thanks!
The problem is fixed and it saves me a tedious maintenance chore.

If you're interested, I had to add in yet another check to make it all
work, and the final gnarly XPath looks like this:

<xsl:variable name="wri"
select="count(items/item[(not(@doc = 'no') and @iname !=
starts-with(@iname,'dr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'hr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'usr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'szr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'ulr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'ipr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'br')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'ucr'))])"/>

Weirdly, "not(@doc = no)" worked when "@doc != 'no'" did not. But I'm
happy.

Mark

Aug 31 '05 #8
ned786 wrote:
Your last suggestion also works, Peter, and you are my hero. Thanks!
The problem is fixed and it saves me a tedious maintenance chore.
My pleasure...
If you're interested, I had to add in yet another check to make it all
work, and the final gnarly XPath looks like this:

<xsl:variable name="wri"
select="count(items/item[(not(@doc = 'no') and @iname !=
starts-with(@iname,'dr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'hr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'usr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'szr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'ulr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'ipr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'br')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'ucr'))])"/>
I'm not clear what this is trying to achieve. @iname is an attribute:
testing its inequality against a boolean like starts-with will probably
have unexpected effects, depending on whether the attribute is present
or not. If present, and starting with 'hr', then the first test should
always evaluate false.
Weirdly, "not(@doc = no)" worked when "@doc != 'no'" did not. But I'm
happy.


I have the feeling I've seen this too...possibly not all processors are
happy with negated boolean conditions involving attributes.

///Peter

Sep 3 '05 #9
Peter Flynn wrote:
<xsl:variable name="wri"
select="count(items/item[(not(@doc = 'no') and @iname !=
starts-with(@iname,'dr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'hr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'usr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'szr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'ulr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'ipr')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'br')) and
(not(@doc = 'no') and @iname != starts-with(@iname,'ucr'))])"/>


I'm not clear what this is trying to achieve. @iname is an attribute:
testing its inequality against a boolean like starts-with will probably
have unexpected effects, depending on whether the attribute is present
or not. If present, and starting with 'hr', then the first test should
always evaluate false.


Here's what this achieves. This XPath finds all the writable <item>
elements for me, because I can identify them when the iname attribute
does NOT start with one of the read-only strings (hr, usr, ulr, etc.).

If you are questioning the syntax of saying "@iname !=
starts-with(@iname,...)" instead of just "!= starts-with(@iname,...)",
I did it that way because it seemed I had to or it didn't work. When I
remove the "@iname !=", I get the error "Unexpected token != in
expression" and it stops the transform. (I'm using Saxon at the command
line.)

I also tried putting the expression in parentheses like (!=
starts-with(@iname,...)), and the same error occurred. It only worked
when I put "@iname != starts-with(@iname,...)".

At this point I think I will just take the money and run. I can count
on there always being an iname attribute.

Thanks again,
Mark

Sep 6 '05 #10
ned786 wrote:
> <xsl:variable name="wri"
> select="count(items/item[(not(@doc = 'no') and @iname !=
> starts-with(@iname,'dr')) and
> (not(@doc = 'no') and @iname != starts-with(@iname,'hr')) and
> (not(@doc = 'no') and @iname != starts-with(@iname,'usr')) and
> (not(@doc = 'no') and @iname != starts-with(@iname,'szr')) and
> (not(@doc = 'no') and @iname != starts-with(@iname,'ulr')) and
> (not(@doc = 'no') and @iname != starts-with(@iname,'ipr')) and
> (not(@doc = 'no') and @iname != starts-with(@iname,'br')) and
> (not(@doc = 'no') and @iname != starts-with(@iname,'ucr'))])"/>


I'm not clear what this is trying to achieve. @iname is an attribute:
testing its inequality against a boolean like starts-with will probably
have unexpected effects, depending on whether the attribute is present
or not. If present, and starting with 'hr', then the first test should
always evaluate false.


Here's what this achieves. This XPath finds all the writable <item>
elements for me, because I can identify them when the iname attribute
does NOT start with one of the read-only strings (hr, usr, ulr, etc.).

If you are questioning the syntax of saying "@iname !=
starts-with(@iname,...)" instead of just "!= starts-with(@iname,...)",
I did it that way because it seemed I had to or it didn't work. When I
remove the "@iname !=", I get the error "Unexpected token != in
expression" and it stops the transform. (I'm using Saxon at the command
line.)


It's the = sign I'm questioning. What about !starts-with or
not(starts-with(...))

I am reminded of the programming language built into the P-Stat stats
package (PPL) which contained the amazingly useful syntax

if any(varname,varname,varname,...) among (value,value,value,...)

:-)

///Peter

Sep 7 '05 #11
I tried out what you suggest.

This works:
(not(@doc = 'no') and not(starts-with(@iname,'dr')))

This doesn't work and stops the transform:
(not(@doc = 'no') and !starts-with(@iname,'dr'))

with this error:
"!" without "=" in expression count(...etc.

Your "not(starts-with..." makes the XPath simpler and easier for
someone to understand, so I'll use it.

Thanks yet again!
Mark

Sep 8 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: loveNUNO | last post by:
Hi ~ Plz Help me ~~ My problem is.. XBRL Sample file ------------------ a.xbrl <?xml version="1.0" encoding="utf-8"?>
1
by: H. Kaya | last post by:
Hallo, I have a problem converting a XML file to a other. I have no idea how I can do this. I try it for a long time but I can not find a solution. Has anyone a Idea? Below you can find my...
7
by: Eivind | last post by:
Hi, I'm creating XML-files from printed documents. According to the DTD I have to use, there has to be pagebreaks in the XML-file. These pagebrakes must be located whenever a new page in the...
0
by: Mike | last post by:
I'm generating an XSLT document programatically in VB.Net. I'm then trying to apply that XSLT against a cXML document to generate my own internally developed XML document. I'm using RichTextBox...
4
by: Moogy | last post by:
I'm pulling my hair out here. First, I'm new to XML, so that doesn't help, but none of this makes any sense to me. All I'm trying to do is take a simple source XML file and translate it with an...
7
by: Harolds | last post by:
The code below worked in VS 2003 & dotnet framework 1.1 but now in VS 2005 the pmID is evaluated to "" instead of what the value is set to: .... xmlItems.Document = pmXML // Add the pmID...
7
by: Coco | last post by:
Hi, I have 2 xml document the A and B, i want to to map some of the data from A to B using XSLT, but without creating a new XML Document. How can i do that? Thanks
2
by: parth | last post by:
I have the following XML file - <root> <book> <section>art</section> <title>abc</title> <author>mark</author> </book> <book> <section>science</section>
2
by: jkflens | last post by:
Hello, i convert one XML-document by using XSLT into another XML-document. First change all attributes to elements is no problem. Then i try to insert a new element into the new document by...
18
by: yinglcs | last post by:
Hi, I have a newbie XSLT question. I have the following xml, and I would like to find out the children of feature element in each 'features' element. i.e. for each <featuresI would like to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.