0

我想避免在我的 XSLT 输出中产生重复的命名空间。

(我正在使用 XSLT 处理一些 XML,以便 Microsoft 的 DataContractSerializer 认为适合实际处理它。DCS 似乎不喜欢的一件事是多次定义相同的命名空间。)

我从 XXX 元素下获取所有“Characteristics”元素,并将它们组合在一个新的数组元素中,如下所示:

<xsl:stylesheet version="1.0" 
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
              xmlns:feature="some namespace">
<xsl:template match="feature:XXX">
  <xsl:copy>
    <feature:Characteristics>
      <xsl:apply-templates select="feature:Characteristics"/>
     </feature:Characteristics>
    <xsl:copy-of select="*[not(self::feature:Characteristics)]" />
  </xsl:copy>
</xsl:template>
<xsl:template match="feature:Characteristics">
  <arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <xsl:value-of select="." />
  </arrays:unsignedShort>
</xsl:template>
</xsl:stylesheet>

“功能”名称空间定义在 XSLT 文件的顶部。然而,在源 XML 中不会找到值“feature”,它将是一些任意前缀(通常是“h”)。问题是,如果我使用这个 XSLT,那么命名空间被分配给输出 XML 中的 2 个前缀:来自输入 XML 的原始命名空间(通常是“h”)和由 XSLT 生成的“特征”。(虽然 XML 有效,但这让可怜的 Microsoft 感到困惑。)

所以我想通过引用当前元素的命名空间来完全避免在输出 XML 中定义“功能”命名空间。我对此尝试了变体,但我不知道如何正确设置 xsl:element 的命名空间值以获取当前上下文节点的命名空间前缀......

<xsl:stylesheet version="1.0" 
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
              xmlns:feature="some namespace">
  <xsl:template match="feature:XXX">
   <xsl:copy>
    <xsl:element name="Characteristics" namespace="{???}">
      <xsl:apply-templates select="feature:Characteristics"/>
    </xsl:element>
    <xsl:copy-of select="*[not(self::feature:Characteristics)]" />
  </xsl:copy>
</xsl:template>
  <xsl:template match="feature:Characteristics">
  <arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <xsl:value-of select="." />
  </arrays:unsignedShort>
</xsl:template>
</xsl:stylesheet>

样本输入:

<h:XXX xmlns:h="http://stackoverflow.com">
 <h:Characteristics>7</h:Characteristics>
 <h:Characteristics>11</h:Characteristics>
 <h:Characteristics>12</h:Characteristics>
 <h:ProductName>blah</h:ProductName>
 <h:Vendor>blah</h:Vendor>
 <h:Version></h:Version>
</h:XXX>

重复命名空间(坏):

<h:XXX xmlns:h="http://stackoverflow.com">
 <feature:Characteristic xmlns:feature="http://stackoverflow.com">
      <arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">7</arrays:unsignedShort>
      <arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">11</arrays:unsignedShort>
      <arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">12</arrays:unsignedShort>
 </feature:Characteristic>
 <h:ProductName>blah</h:ProductName>
 <h:Vendor>blah</h:Vendor>
 <h:Version></h:Version>
</h:XXX>

期望的输出:

<h:XXX xmlns:h="http://stackoverflow.com">
 <h:Characteristic>
      <arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">7</arrays:unsignedShort>
      <arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">11</arrays:unsignedShort>
      <arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">12</arrays:unsignedShort>
 </h:Characteristic>
 <h:ProductName>blah</h:ProductName>
 <h:Vendor>blah</h:Vendor>
 <h:Version></h:Version>
</h:XXX>

这个 XSLT 几乎可以工作,但它涉及硬编码“h”值,我想支持任意值:

<?xml version ="1.0" encoding="iso-8859-1"?>
  <xsl:stylesheet version="1.0" 
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
              xmlns:feature="some ns"
              xmlns:h="some ns"
              exclude-result-prefixes="h">

<xsl:template match="feature:XXX">
  <xsl:copy>
    <h:Characteristic>
      <xsl:apply-templates select="feature:Characteristics"/>
    </h:Characteristic>
    <xsl:copy-of select="*[not(self::feature:Characteristics)]" />
  </xsl:copy>
</xsl:template>

<xsl:template match="feature:Characteristics">
  <arrays:unsignedShort xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <xsl:value-of select="." />
  </arrays:unsignedShort>
 </xsl:template>

 </xsl:stylesheet>
4

3 回答 3

1

我刚刚删除了那个feature命名空间;如果我理解正确,它将包含与 相同的 URI h,对吗?

<xsl:stylesheet version="1.0"
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
              xmlns:h="http://stackoverflow.com">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="h:XXX" >
    <xsl:copy>
      <h:Characteristics>
        <xsl:apply-templates select="h:Characteristics"/>
      </h:Characteristics>
      <xsl:copy-of select="*[not(self::h:Characteristics)]" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="h:Characteristics">
    <arrays:unsignedShort 
        xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
      <xsl:value-of select="." />
    </arrays:unsignedShort>
  </xsl:template>
</xsl:stylesheet>
于 2010-01-06T00:20:00.107 回答
1

这似乎对我有用,我相信一定有一个更简单的方法,但我现在无法思考。所有这一切都使用name()函数来获取根名称的前缀名称,substring-before()来获取前缀,然后重建值并将它们作为非转义文本发出。

<xsl:stylesheet version="1.0" 
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
          xmlns:feature="http://stackoverflow.com"
      exclude-result-prefixes="feature" >
<xsl:template match="feature:XXX">
  <xsl:variable name="p" select="substring-before(name(), ':')"/>
  <xsl:copy>
   <xsl:value-of select="concat('&lt;', $p,':Characteristic', '&gt;')" disable-output-escaping="yes"/>
   <xsl:apply-templates select="feature:Characteristics"/>
   <xsl:value-of select="concat('&lt;/', $p,':Characteristic', '&gt;')" disable-output-escaping="yes"/>
   <xsl:copy-of select="*[not(self::feature:Characteristics)]" /> 
 </xsl:copy>
</xsl:template>
  <xsl:template match="feature:Characteristics">
   <arrays:unsignedShort 
       xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
     <xsl:value-of select="." />
   </arrays:unsignedShort>
 </xsl:template>
</xsl:stylesheet>
于 2010-01-06T01:13:39.823 回答
1

如果您想要一致的命名空间前缀,那么您将需要生成新元素,而不是copy-of。在 XSLT 中将您的名称空间前缀设置为您希望的任何内容(功能、h 等)。

以下 XSLT:

<xsl:stylesheet version="1.0"
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
              xmlns:feature="http://stackoverflow.com"
              xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
  <xsl:output method="xml" indent="yes" />

  <xsl:template match="feature:XXX">
   <xsl:element name="feature:XXX">
    <feature:Characteristic>
      <xsl:apply-templates select="feature:Characteristics"/>
    </feature:Characteristic>
    <xsl:apply-templates select="*[not(self::feature:Characteristics)]" />
  </xsl:element>
  </xsl:template>

  <xsl:template match="feature:Characteristics">
    <xsl:element name="arrays:unsignedShort">
        <xsl:value-of select="." />
    </xsl:element>
  </xsl:template>

  <xsl:template match="*">
     <xsl:element name="feature:{local-name()}" >
        <xsl:value-of select="." />
     </xsl:element>
  </xsl:template>

</xsl:stylesheet>

生成以下输出:

<?xml version="1.0" encoding="UTF-16"?>
<feature:XXX xmlns:feature="http://stackoverflow.com">
 <feature:Characteristic xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
  <arrays:unsignedShort>7</arrays:unsignedShort>
  <arrays:unsignedShort>11</arrays:unsignedShort>
  <arrays:unsignedShort>12</arrays:unsignedShort>
 </feature:Characteristic>
 <feature:ProductName>blah</feature:ProductName>
 <feature:Vendor>blah</feature:Vendor>
 <feature:Version></feature:Version>
</feature:XXX>
于 2010-01-06T01:46:34.423 回答