使用XSLT在XML中预处理#ifdefs

时间:2012-09-05 13:29:47

标签: xml xslt preprocessor

这可能是Using XSLT as an XML pre-processor的几乎副本。但由于该问题的OP没有发布完整的例子,尽管被要求,但回复对任何不熟悉XSLT的人都没用。没有广泛的网络搜索提供任何有用的东西 - XSLT似乎记录非常糟糕,很少在网上讨论。

无论如何......

我有一个XML文件,比如说foo.xml,如下所示(很明显很简化):

 <?xml version="1.0" encoding="UTF-8"?>

 <main>

  <fee>blah</fee>

  <ifdef select="OLD_VERSION">
   <fi>blah blah</fi>
  </ifdef>

  </main>

(根据Ian Roberts的回答,C风格#ifdef更改为“ifdef”块)

我想在linux上运行xsltproc命令,如下所示:

xsltproc --stringparam xmlver NEW_VERSION --nonet foo.xslt foo.xml

并使用以下XSLT文件foo.xslt来排除#ifdef'ed部分:

<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>

(我确实使用了上面提到的问题的答案来构建这个XSLT;但缺少的成分是在哪里/如何合并“xmlver”值。当然不能保证它在上面是正确的;但是这个基本上我要问的是 - 这一切如何以一种有效的方式组合在一起?)

任何建设性的回复都将受到高度赞赏,并且无疑对将来有类似要求的许多人有用;但请不要厌倦,教条“你为什么要那样做?”回复!

3 个答案:

答案 0 :(得分:1)

您提到的问题看起来像是基于XML结构,它使用XML元素作为其ifdef。在您的情况下,#ifdef行不是XML元素,因此您无法将它们与XSLT模板匹配。如果需要对其进行其他XML感知处理,最好使用非XML工具(可能甚至是普通的C预处理器)来处理ifdef并将生成的XML提供给XSLT。

如果您愿意为ifdef使用真实的XML元素,就像上一个问题一样:

<?xml version="1.0" encoding="UTF-8"?>
<main>
  <fee>blah</fee>

  <ifdef select="OLD_VERSION">
   <fi>blah blah</fi>
  </ifdef>

</main>

那么问题就变成了如何将xmlver命令行参数视为要包含的单个ifdef,而不是作为从中加载一整套定义的文件的位置(这是如何上一个问题有效)。这更简单:

<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>

我之前的尝试使用了<xsl:template match="ifdef[@select=$xmlver]">,它在某些处理器中有效但在xsltproc中不起作用(它是technically not allowed by the XSLT spec,并且xsltproc比我通常的测试工具Xalan更严格。

答案 1 :(得分:1)

建议:您可以使用m4吗?

代替xsltproc
<?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>

答案 2 :(得分:0)

我想从你的一般方法开始:

  

回复对任何不熟悉XSLT的人都没用。也没有   广泛的网络搜索出现了任何有用的东西 - XSLT似乎   在网上很少记录和讨论很少。

这基本上告诉我们您正在尝试用您不熟悉的语言编写程序,并且您正试图通过Google搜索来查找有关该语言的信息。这是一个很好的学习策略吗?

我原以为你的问题是点击次数太多而不是太少,例如“XSLT教程”给出了2,300,000次点击。最重要的都值得一读。将其描述为“记录不清,很少讨论”似乎很奇怪。

就个人而言,如果我要开始用新语言编程,我总是先阅读一本关于这个主题的书。在线资料很少像教科书一样经过精心设计,编写和审核。当然我会说,因为我是最流行的XSLT参考书之一的作者,但我认为这是真的。

现在,我可以帮您解决问题吗?不是,我很遗憾。有些人使用经过测试的代码回复此论坛上的问题,您可以在不理解的情况下使用这些代码。我没有:我只是指出人们正确的方向;而且我不打算用你不懂的语言给你代码片段。在这种情况下,指向正确的方向意味着在尝试使用之前告诉您学习该语言。