xml - 使用 XSLT 预处理 XML 中的 #ifdef

标签 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” block )

我想在 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”值。当然不能保证上面的内容是正确的;但是这个本质上我要问的是——所有这些是如何以一种有效的方式组合在一起的?)

任何建设性的回复将不胜感激,并且无疑对将来有类似需求的许多人有用;但请不要提出令人厌烦的、教条式的“你为什么要这么做?”回复!

最佳答案

您提到的问题看起来像是基于 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 更严格)。

关于xml - 使用 XSLT 预处理 XML 中的 #ifdef,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12282611/

相关文章:

php - xml + xpath,打印元素

android - 错误 : <item> inner element must either be a resource reference or empty

xml - XSLT - 选择没有属性的节点

c - 确保只将指针传递给可变参数函数

c - 如何将参数传递给函数并在其中的宏函数中使用这些参数

c# - 使用 Linq 和 XDocument,我可以获取父标签下的所有子元素吗?

java - EditView 在单击时执行操作

java - 捕获 xsl 结果文档的输出流

java - 在 JAVA 中使用 XSLT 将 XML 元素从小写转换为大写

python - 如何使用for循环在python3中使用不同的预处理函数?