I've done some looking around, but I'm not seeing an obvious answer to my problem. I'm sure I'm overlooking something, but I don't know what.
I've done some preprocessing on the XML below to edit some of the element names, and after preprocessing I have an XSL stylesheet that does a simple identity transform. However, I'm wondering if there's a way to avoid the preprocessing step and accomplish everything in one stylesheet. The primary difference between the two XML inputs are <subj*>
has become <subj>
.
Is there a method for testing an element name for a starting (or ending, too, I suppose) value? Thanks very much for your time & suggestions.
I have XML input that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<issueNumber>1.001</issueNumber>
<subj1>Cats</subj1>
<subj2>LOLCats</subj2>
<subj3>Cheezburgers</subj3>
<subj4></subj4>
</row>
<row>
<issueNumber>2.001</issueNumber>
<subj1>Cats</subj1>
<subj2>LOLCats</subj2>
<subj3>NOMS</subj3>
<subj4>Cheezburger</subj4>
</row>
<row>
<issueNumber>3.001</issueNumber>
<subj1>NOMS</subj1>
<subj2></subj2>
<subj3></subj3>
<subj4></subj4>
</row>
</root>
I'm processing it with the following XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="row">
<!--<xsl:result-document href="{concat(issueNumber, '.xml')}">-->
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
<!--</xsl:result-document>-->
</xsl:template>
<xsl:template match="issueNumber">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="subj">
<xsl:choose>
<xsl:when test="not(string(.))"></xsl:when>
<xsl:when test="string(.)">
<subject>
<xsl:apply-templates />
</subject>
</xsl:when>
</xsl:choose>
</xsl:template>
If I understand the question correctly, you could do something like this:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(name(),'subj')]">
<subj>
<xsl:if test="string(.)">
<subject>
<xsl:apply-templates/>
</subject>
</xsl:if>
</subj>
</xsl:template>
</xsl:stylesheet>
Using your XML input (corrected to be well-formed):
<root>
<row>
<issueNumber>1.001</issueNumber>
<subj1>Cats</subj1>
<subj2>LOLCats</subj2>
<subj3>Cheezburgers</subj3>
<subj4></subj4>
</row>
<row>
<issueNumber>2.001</issueNumber>
<subj1>Cats</subj1>
<subj2>LOLCats</subj2>
<subj3>NOMS</subj3>
<subj4>Cheezburger</subj4>
</row>
<row>
<issueNumber>3.001</issueNumber>
<subj1>NOMS</subj1>
<subj2></subj2>
<subj3></subj3>
<subj4></subj4>
</row>
</root>
Produces the following output:
<root>
<row>
<issueNumber>1.001</issueNumber>
<subj>
<subject>Cats</subject>
</subj>
<subj>
<subject>LOLCats</subject>
</subj>
<subj>
<subject>Cheezburgers</subject>
</subj>
<subj/>
</row>
<row>
<issueNumber>2.001</issueNumber>
<subj>
<subject>Cats</subject>
</subj>
<subj>
<subject>LOLCats</subject>
</subj>
<subj>
<subject>NOMS</subject>
</subj>
<subj>
<subject>Cheezburger</subject>
</subj>
</row>
<row>
<issueNumber>3.001</issueNumber>
<subj>
<subject>NOMS</subject>
</subj>
<subj/>
<subj/>
<subj/>
</row>
</root>
Are you searching for something like "regex" in XSLT? If you are, this link might be very useful for you: http://www.w3.org/TR/xslt20/#regular-expressions
However, this solution only works in XSLT 2.0. You might lose compatibility to older XSLT versions.
starts-with()
in xsl:template match="..."
- CanOfBees 2012-04-04 20:05
</root>
over far enough - sorry about that. your stylesheet is closest with the succinct usage ofxsl:template match="*[starts-with...]"
. thanks, very much, for the help - CanOfBees 2012-04-04 20:11