3

我有一个 XSL,我需要按照以下方式生成输出:

<moo xmlns="http://api.example.com">
    <foo>1358944586848</foo>
    <bar>
        <a>1</a>
        <b>2</b>
        <c>3</c>
    </bar>
</moo>

我可以这样做:

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

    <xsl:template match="/">
        <xsl:element name="moo">
            <!-- and so on -->

但是,我有点讨厌在我的 xsl 文件中使用 xsl 前缀,因为我觉得它很混乱。无论如何,使用 XPath 选择很容易,因为您可以根据xpath-default-namespace需要设置要转换的任何内容。但element-default-namespace据我所知,没有可用的,那么我怎样才能以一种好的方式生成想要的输出呢?

我知道我可以这样做:

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

    <template match="/">
        <element name="moo" namespace="http://api.example.com">
            <!-- and so on -->

但是我必须在我创建的每个元素上显式地设置这个命名空间,否则它们最终将使用 XSL 命名空间。那么有没有一种干净的方法来创建具有特定命名空间(没有前缀)的元素并且不触及 xsl 文件的默认命名空间?


更新:

认为也许namespace-alias可以做一些事情,但无法弄清楚如何使用它。试过这个,但似乎对输出没有任何影响:

<stylesheet version="2.0"
    xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:out="http://api.example.com">

<namespace-alias stylesheet-prefix="out" result-prefix=""/>

    <template match="/">
        <element name="out:moo">
            <!-- and so on -->

事情可能没有按照namespace-alias我的想法做:p

我使用的最终解决方案,基于 JLRishe 的回答

删除前缀.xsl

<?xml version="1.0" encoding="UTF-8"?>
<stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform">
    <template match="/">
        <variable name="result">
            <next-match />
        </variable>
        <apply-templates select="$result" mode="remove-prefixes" />
    </template>

    <template match="*" priority="1" mode="remove-prefixes">
        <element name="{local-name()}" namespace="{namespace-uri()}">
            <apply-templates select="@* | node()" mode="remove-prefixes" />
        </element>
    </template>
    <template match="@*|node()" mode="remove-prefixes">
        <copy>
            <apply-templates select="@* | node()" mode="remove-prefixes" />
        </copy>
    </template>

</stylesheet>

主题.xsl

<!-- snip -->
<import href="remove-prefixes.xsl" />
<!-- snip -->
4

3 回答 3

3

您可以做的一件事是在一个变量中捕获 XSL 的整个结果,然后在最后清除其前缀:

<stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform"
                          xmlns:p="http://api.example.com">
  <output method="xml" indent="yes"/>

  <template match="/">
    <variable name="result">
      <p:moo>
        <apply-templates />
      </p:moo>
    </variable>
    <apply-templates select="$result" mode="removePrefix" />
  </template>

  <template match="root">
    <p:something hello="hi">
      <element name="p:somethingelse" />
    </p:something>
  </template>

  <template match="p:*" mode="removePrefix">
    <element name="{local-name()}" namespace="{namespace-uri()}">
      <apply-templates select="@* | node()" mode="removePrefix" />
    </element>
  </template>

  <template match="@* | node()" mode="removePrefix">
    <copy>
      <apply-templates select="@* | node()" />
    </copy>
  </template>
</stylesheet>

在此输入上运行时:

<root>
  <top />
</root>

它产生:

<moo xmlns="http://api.example.com">
  <something hello="hi">
    <somethingelse />
  </something>
</moo>
于 2013-01-23T13:16:59.747 回答
1

-xmlns:xsl方法实际上是“标准”的一天,我想 XSL 的设计者已经想到了这一点。

请记住,您可以将 XML 片段直接混合到 XSL 中。从这个角度来看,您的方法xsl:element可以说比您尝试使用“元素默认命名空间”消除的方法增加了更多的噪音和混乱。

所以,我会这样做:

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

    <xsl:template match="/">
        <moo>
            <!-- and so on -->

编辑:

以下namespace-alias可能有效:

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

    <namespace-alias stylesheet-prefix="xsl" result-prefix="#default"/>

    <template match="/" xmlns="http://www.w3.org/1999/XSL/Transform">
        <element name="moo">
            <!-- etc -->

或者像这样:

<stylesheet version="2.0"
    exclude-result-prefixes="api" 
    xmlns="http://www.w3.org/1999/XSL/Transform"
    xmlns:api="http://api.example.com">

    <namespace-alias stylesheet-prefix="#default" result-prefix="api"/>

    <template match="/">
        <element name="moo">
            <!-- etc -->
于 2013-01-23T12:55:36.063 回答
0

我对混乱的感觉和你一样,特别是如果我有样式表,其中绝大多数元素都在 XSL 命名空间中,而不是在目标命名空间中。解决方案很简单:给输出元素一个前缀而不是 XSL 元素:

<stylesheet version="2.0"
    xmlns="http://www.w3.org/1999/XSL/Transform"
    xmlns:o="http://api.example.com">

    <template match="/">
        <o:moo>
            <!-- and so on -->
于 2013-01-23T12:58:34.790 回答