问题
This is presumably an almost carbon copy of Using XSLT as an XML pre-processor But as the OP of that question did not post a full example, despite being asked to, the replies are no use to anyone not familiar with XSLT. Neither have extensive web searches turned up anything helpful - XSLT seems remarkably poorly documented and little discussed on the Web.
Anyway ...
I have an XML file, say foo.xml, as follows (greatly simplified, obviously):
<?xml version="1.0" encoding="UTF-8"?>
<main>
<fee>blah</fee>
<ifdef select="OLD_VERSION">
<fi>blah blah</fi>
</ifdef>
</main>
(C-style #ifdef changed to "ifdef" block in light of Ian Roberts's answer)
I want to run an xsltproc command on linux, as follows:
xsltproc --stringparam xmlver NEW_VERSION --nonet foo.xslt foo.xml
and have this use the following XSLT file, foo.xslt, to exclude the #ifdef'ed section:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:param name="xmlver" required="yes"/>
<xsl:template match="node() | @*">
<xsl:copy><xsl:apply-templates select="node() | @*"/></xsl:copy>
</xsl:template>
<xsl:variable name="defines" select="document($xmlver)/defines"/>
<xsl:template match="ifdef">
<xsl:variable name="this" select="."/>
<xsl:for-each select="$defines[def = $this/@select]">
<xsl:apply-templates select="$this/node()" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
(I did use the replies to the question referenced above to construct this XSLT; but the missing ingredient is where/how to incorporate the "xmlver" value. Of course there is no guarantee it is correct in the above; but this essentially what I am asking - How is all this put together in a way that works?)
Any constructive replies will be greatly appreciated, and will doubtless be useful to many people with a similar requirement in the future; but please no tiresome, dogmatic "Why would you want to do that?" replies!
回答1:
The question you refer to looks like it's based on an XML structure that uses XML elements for its ifdefs. In your case your #ifdef
lines are not XML elements, so you can't match them with an XSLT template. You'd be better off using a non-XML tool (possibly even the normal C pre-processor) to handle the ifdefs and feed the resulting XML to an XSLT if you need to do other XML-aware processing on it.
If you're happy to use real XML elements for your ifdefs, as in the previous question:
<?xml version="1.0" encoding="UTF-8"?>
<main>
<fee>blah</fee>
<ifdef select="OLD_VERSION">
<fi>blah blah</fi>
</ifdef>
</main>
then the question becomes how to treat the xmlver command line parameter as the single ifdef
that you want to include, rather than as the location of a file from which to load a whole set of defines (which is how the previous question worked). That is much simpler:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:param name="xmlver" />
<xsl:template match="node() | @*">
<xsl:copy><xsl:apply-templates select="node() | @*"/></xsl:copy>
</xsl:template>
<xsl:template match="ifdef">
<!-- for the ifdef we want, include all its child elements, text nodes etc
but not its attributes, for other ifdefs do nothing -->
<xsl:if test="@select = $xmlver">
<xsl:apply-templates select="node()" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
My previous attempt at this used a <xsl:template match="ifdef[@select=$xmlver]">
, which works in some processors but not in xsltproc (it is technically not allowed by the XSLT spec, and xsltproc is stricter than my usual test harness, Xalan).
回答2:
suggestion: instead of xsltproc, can you just use m4 ?
<?xml version="1.0" encoding="UTF-8"?>
<main>
<fee>blah</fee>
ifdef(`X',`
<fi>blah blah</fi>
')
</main>
.
$ m4 jeter.xml
<?xml version="1.0" encoding="UTF-8"?>
<main>
<fee>blah</fee>
</main>
.
$ m4 -DX jeter.xml
<?xml version="1.0" encoding="UTF-8"?>
<main>
<fee>blah</fee>
<fi>blah blah</fi>
</main>
回答3:
I'd like to start with your general approach:
the replies are no use to anyone not familiar with XSLT. Neither have extensive web searches turned up anything helpful - XSLT seems remarkably poorly documented and little discussed on the Web.
This basically tells us that you are trying to write a program in a language you are not familiar with, and that you are trying to find information about that language by googling for it. Is that a good learning strategy?
I would have thought your problem was too many hits rather than too few, for example "XSLT tutorial" gives 2,300,000 hits. The top ones are all well worth a read. It seems odd to describe that as "poorly documented and little discussed".
Personally though if I'm going to start programming in a new language I always start by reading a book on the subject. Online material is rarely as carefully designed, written and reviewed as a text book. Of course I would say that since I'm the author of one of the most popular XSLT reference books, but I think it's true nonetheless.
Now, can I help you with your problem. Not really, I regret. Some people respond to questions on this forum with working tested code that you can use without understanding it. I don't: I simply point people in the right direction; and I'm not going to give you fragments of code in a language you don't understand. Pointing you in the right direction in this case means telling you to learn the language before you try using it.
来源:https://stackoverflow.com/questions/12282611/using-xslt-to-preprocess-ifdefs-in-xml