Multi-input file XSLT problem

N

ned786

I have a list of files like this in a file called docs.xml:

<docroot>
<root href="file:///C:/doc_source/aaa.xml" />
<root href="file:///C:/doc_source/bbb.xml" />
<root href="file:///C:/doc_source/ccc.xml" />
</docroot>

I pass in docs.xml and parse it like this, outputting an xml file:

<xsl:template match="/">
<root>
<class>
<xsl:apply-templates select="document(docroot/root/@href, .)/
root/class/property">
<xsl:sort select="@name" lang="en"/>
</xsl:apply-templates>
</class>
</root>
</xsl:template>

<xsl:template match="property">
<xsl:copy-of select="."/>
</xsl:template>

There are a lot of repeated items in these external files and I get a
result doc like this:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<class>
<property name="Active"/>
<property name="Active"/>
<property name="Active"/>
<property name="Inactive"/>
<property name="Inactive"/>
<property name="Inactive"/>
<property name="Synchronous"/>
<property name="Synchronous"/>
<property name="Synchronous"/>
</class>
</root>

There might be 2 Active <property>s from aaa.xml, then the next comes
from bbb.xml etc. How can I get just one of each (one <property
name="Active">, one <property name="Inactive">, etc) in my output
doc?

I'm using Saxon 8.7.1J.

Thanks,
Mark
 
M

Manuel Collado

ned786 escribió:
...
There are a lot of repeated items in these external files and I get a
result doc like this:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<class>
<property name="Active"/>
<property name="Active"/>
<property name="Active"/>
<property name="Inactive"/>
<property name="Inactive"/>
<property name="Inactive"/>
<property name="Synchronous"/>
<property name="Synchronous"/>
<property name="Synchronous"/>
</class>
</root>

There might be 2 Active <property>s from aaa.xml, then the next comes
from bbb.xml etc. How can I get just one of each (one <property
name="Active">, one <property name="Inactive">, etc) in my output
doc?

Perhaps by applying a second transformation like (untested):

<xsl:template match="property">
<xsl:variable name="name" select="@name"/>
<xsl:if test="not(preceding::property@name=$name])">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>

Regards.
 
M

Martin Honnen

ned786 said:
There might be 2 Active <property>s from aaa.xml, then the next comes
from bbb.xml etc. How can I get just one of each (one <property
name="Active">, one <property name="Inactive">, etc) in my output
doc?

I'm using Saxon 8.7.1J.

Note that the latest Saxon version is 8.9.0.4 which implements the XSLT
2.0 specification.
With that Saxon version this stylesheet works for me:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">

<xsl:eek:utput method="xml" indent="yes"/>

<xsl:template match="/">
<root>
<class>
<xsl:for-each-group select="document(docroot/root/@href,
..)/root/class/property" group-by="@name">
<xsl:sort select="@name" lang="en"/>
<xsl:apply-templates select="current-group()[1]"/>
</xsl:for-each-group>
</class>
</root>
</xsl:template>

<xsl:template match="property">
<xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>
 
J

Joe Kesselman

Manuel said:
Perhaps by applying a second transformation like (untested):

As noted in the "Double-Transformation" thread, the second
transformation could even be done in the same stylesheet, if you're
willing to use either the nodeset extension function or XSLT 2.0.
(Transform into a variable, then reprocess from that, possibly using
modes to distinguish the passes.)
 
N

ned786

Thanks for the responses to my post, I appreciate them. I didn't try
them all because the XSLT 2.0 <xsl:for-each-group> instruction worked
for me. Here's the code that worked, it includes the key functions I
left out of my original simplified post:

<xsl:for-each-group select="document(docroot/root/@href, .)/
root/class/property" group-by="@name">
<!-- variable holds the name of this property -->
<xsl:variable name="thisprop" select="@name"/>
<!-- variable holds the name of this class -->
<xsl:variable name="thisclass" select="../@name"/>

<xsl:choose>
<xsl:when test="exists(key('ext-prop-wr', $thisprop, $auto-
descript)) and
not(exists($auto-descript/root/writable/property[@name =
$thisprop]/exclude/class[@name = $thisclass]))">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:eek:therwise/>
</xsl:choose>
</xsl:for-each-group>

Regards,
Mark
 
N

ned786

I tried this second-transform-in-the-same-stylesheet with XSLT 2.0,
and it works great. It saves a lot of work on a second transform.
Thanks.

Mark
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top