473,503 Members | 2,075 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Match an attribute value in a set of possible values

Hi All,

given the source document:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<child>
<test id="1" name="first child"/>
</child>
<child>
<test id="2" name="second child"/>
</child>
<child>
<test id="3" name="third child"/>
</child>
</root>

I would suppress the the child elements that contain a test element
with the value of the id attribute in a list of known ids; for
instance, assuming that the list of ids to remove is {1,3}, I would
obtain the document:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<child>
<test id="2" name="second child"/>
</child>
</root>

where only the second child element is retained.

I'm only able to suppress a single child element using the following
XSL transform;

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child[test[@id='1']]"/>
</xsl:stylesheet>

Is it possible to match and suppress multiple child elements whose ids
are contained in a given list ?

Since I'm invoking the transform from Java, I would like to set a
template parameter to the list of ids to be removed; e.g. as comma
delimited list, and write the last match condition as something like
this:

....
<xsl:param name="idToRemove" select="default" />
<xsl:template match="child[test[@id in $idsToRemove]]"/>
....

Note that I'm using XSLT 1.0, so I cannot leverage the enhancements of
XSLT 2.0, but I'm wondering if there is some trick to do the job; for
instance injecting the list of ids to remove into the same XSLT
document and then iterating over them and suppressing any matching
child element from the source document... maybe something like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:data="http://sample.array.parameters/data" version="1.0">
<xsl:output method="xml" indent="yes" />
<data:parameters>
<id>1</id>
<id>3</id>
</data:parameters>
<xsl:variable name="parameters-root"
select="document('')/*/data:parameters"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child[test[@id in $parameters-root]]"/>
</xsl:stylesheet>

Thanks a lot for any suggestion

Regards,

Patrizio

Sep 1 '06 #1
5 1779


patrin wrote:
<xsl:template match="child[test[@id='1']]"/>
Well an or is possible in XPath 1.0

<xsl:template match="child[test[@id='1' or @id = '3']]"/>
--

Martin Honnen
http://JavaScript.FAQTs.com/
Sep 1 '06 #2

Martin Honnen wrote:
patrin wrote:
<xsl:template match="child[test[@id='1']]"/>

Well an or is possible in XPath 1.0

<xsl:template match="child[test[@id='1' or @id = '3']]"/>
--

Martin Honnen
http://JavaScript.FAQTs.com/
Thanks for the quick replay, but the list of ids to match is dynamyc
and I know it only from Java code, where it is stored into a String
arrray:

String[] idsToRemove = {1,3,...};

and I would like to pass it to the Transformer, invoking the method:

setParameter("idsToRemove", idsToRemove);

so that the XSLT should remove all the child elements whose test
subelement has an id with any of the values contained in the
idsToRemove array.

Is it possible to do this with XSLT 1.0 ? or can you suggest an
alternative way to solve the problem ?

Thanks again for your help

Regards,

Patrizio

Sep 1 '06 #3
patrin wrote:
setParameter("idsToRemove", idsToRemove);
Well, you're unlikely to be able to pass in an array of strings and do
anything useful with it except (maybe) pass it back out to an extension
function. Xalan, for example, will treat that as a "non-XSLT type".

I'd suggest reformatting the data as a single string, which most
processors should treat as an XSLT string value, and then doing string
manipulation to check if the ID is contained in that list. I did a
quick-and-dirty version of that in my styling-stylesheets article; since
it was just an illustration I didn't make it highly robust but you could
make it stronger by checking delimiters.

Alternatively, some processors (again, Xalan is one of these) may let
you pass in a DOM node and have XSLT treat it as a node-set. If you
construct a tree where one element has each of the values, you could
then do an XSLT node-set comparison (does any node in one set equal any
node in the other set). The stylesheet would be cleaner, but the
preparation would be more complex. I'm not sure how portable this
approach would be; the TrAX APIs don't make any particular promises
about how non-string parameters will be processed.

Alternatively: Build that nodes-I'm-interested-in XML document as text,
and put it somewhere that the stylesheet can access via the document()
function. Less efficient, but it gives you the simple "does anything
equal" syntax in the stylesheet, and it may be more portable than
relying on the API to do something useful with Nodes.
--
Joe Kesselman / Beware the fury of a patient man. -- John Dryden
Sep 1 '06 #4


patrin wrote:

Thanks for the quick replay, but the list of ids to match is dynamyc
and I know it only from Java code, where it is stored into a String
arrray:

String[] idsToRemove = {1,3,...};

and I would like to pass it to the Transformer, invoking the method:

setParameter("idsToRemove", idsToRemove);

so that the XSLT should remove all the child elements whose test
subelement has an id with any of the values contained in the
idsToRemove array.

Is it possible to do this with XSLT 1.0 ?
I guess there are two approaches, one that might be processor dependent
where you need to look at the documentation of the XSLT processor what
kind of types you can pass in with setParameter:

The setParameter method
<http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/transform/Transformer.html#setParameter(java.lang.String,%20 java.lang.Object)>
as the second argument takes any object so it might well be that it
works to pass in a Source (e.g. DOMSource or SAXSource or StreamSource)
there as well. But details depend on the XSLT processor, I don't think I
have tried that so far with Saxon or Xalan.
The second approach would take the XSLT stylesheet as an XML document
and change it as needed depending on your idsToRemove before the
stylesheet is used for the transformation.
--

Martin Honnen
http://JavaScript.FAQTs.com/
Sep 1 '06 #5
As others have commented, there are different way to structure the
externally passed parameter or even to modify dynamically the stylesheet, so
that passing a parameter will not be necessary.

But your initial question was how to find that the @id attribute of the
current element is part of ids list, encoded as a coma-delimited string. One
way to determine this is using the following XPath 1.0 expression:

contains($idList, concat(' ', @id, ','))

This will work if every id in the list starts with at least one space and is
followed immediately by a coma. The global parameter itself will have to be
produced and passed to the stylesheet by an implementation-dependent
component -- as this varies for different XSLT processors, one needs to
study the documentation of the specific XSLT processor used in order to
understand how this should be done.

Certainly there are ways to perform more precise tokenization (one example
is the tokenization implemented in the FXSL library), but this simple
solution is probably good just for a start.

Cheers,
Dimitre Novatchev

"patrin" <pa****************@googlemail.comwrote in message
news:11**********************@m73g2000cwd.googlegr oups.com...
Hi All,

given the source document:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<child>
<test id="1" name="first child"/>
</child>
<child>
<test id="2" name="second child"/>
</child>
<child>
<test id="3" name="third child"/>
</child>
</root>

I would suppress the the child elements that contain a test element
with the value of the id attribute in a list of known ids; for
instance, assuming that the list of ids to remove is {1,3}, I would
obtain the document:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<child>
<test id="2" name="second child"/>
</child>
</root>

where only the second child element is retained.

I'm only able to suppress a single child element using the following
XSL transform;

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child[test[@id='1']]"/>
</xsl:stylesheet>

Is it possible to match and suppress multiple child elements whose ids
are contained in a given list ?

Since I'm invoking the transform from Java, I would like to set a
template parameter to the list of ids to be removed; e.g. as comma
delimited list, and write the last match condition as something like
this:

...
<xsl:param name="idToRemove" select="default" />
<xsl:template match="child[test[@id in $idsToRemove]]"/>
...

Note that I'm using XSLT 1.0, so I cannot leverage the enhancements of
XSLT 2.0, but I'm wondering if there is some trick to do the job; for
instance injecting the list of ids to remove into the same XSLT
document and then iterating over them and suppressing any matching
child element from the source document... maybe something like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:data="http://sample.array.parameters/data" version="1.0">
<xsl:output method="xml" indent="yes" />
<data:parameters>
<id>1</id>
<id>3</id>
</data:parameters>
<xsl:variable name="parameters-root"
select="document('')/*/data:parameters"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child[test[@id in $parameters-root]]"/>
</xsl:stylesheet>

Thanks a lot for any suggestion

Regards,

Patrizio

Sep 2 '06 #6

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

Similar topics

1
3417
by: Ravi | last post by:
My XML looks like: <role type="Joker"> <Profile id="13">ABC_Organization</Profile> </role> My XSL looks like: <xsl:variable name="prefix">profile_joker_</xsl:variable> <xsl:variable...
0
2169
by: Carl | last post by:
Hi, I have found a way to map attributes (columns) to column headings. But this runs really slow. Is there a way to improve it? Thanks, Carl <?xml version="1.0" encoding="utf-8" ?>...
0
1471
by: Ingrid | last post by:
Am I right in thinking that datatyping at element level ie <xs:element name="num" type="xs:integer"> and specifying a choice of attribute values ie <xs:attribute name="kind"> <xs:simpleType>...
5
2149
by: Gerald Aichholzer | last post by:
Hello NG, I have an XHMTL-file and would like to replace attribute values using XSLT. The XHTML-file contains the following code: <applet code="MyApplet/MyApplet.class"...
2
3944
by: Bill Cohagan | last post by:
In my app I'm validating an XML file against an XSD which contains several attribute default value specifications. I'm performing the validation via an xml document load() using a...
10
42923
by: Jon Noring | last post by:
Out of curiosity, may a CDATA section appear within an attribute value with datatype CDATA? And if so, how about other attribute value datatypes which accept the XML markup characters? To me,...
5
2858
by: Soledad Vel | last post by:
Hi All, i write this code: var sliderwidth=100; var sliderheight = 100; var div1 = document.createElement('div'); div1.setAttribute('id','d5'); div1.setAttribute('style',...
4
7904
by: rossable | last post by:
The issue is that I need to place an a tag around an image in a .xslt file. Structurally and logically I don't see why this isn't working. <td class="bluecontent_head10d" colSpan="4"> <div...
3
2181
markmcgookin
by: markmcgookin | last post by:
Hi, I have the following XML <AnswerList xmlns="http://tempuri.org/ALPS_Assessmentv1p1_RESCO_Schema.xsd"> <DateTimeLastSaved>12:12:12 1900</DateTimeLastSaved> <UserName>Bob</UserName>...
0
7193
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
7264
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7316
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
6975
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
7449
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
4992
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
3160
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
3148
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
371
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

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.