XSLT 没有产生预期的结果

XSLT not producing desired result

我正在尝试将 XML 文档转换为 CSV,这是我之前成功完成的事情,但是我当前的 XML 的结构有所不同,因为所有子节点元素命名相同(值)。这是 XML:

    <?xml version="1.0" encoding="utf-8"?>
<dataset  xmlns="http://developer.cognos.com/schemas/xmldata/1/" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
    <metadata>
          <item name="Employee Number" type="xs:string" length="20"/>
          <item name="Last Name" type="xs:string" length="202"/>
          <item name="First Name" type="xs:string" length="202"/>
    </metadata>
    <data>
        <row>
            <value>000056</value>
            <value>Atkinson</value>
            <value>Joan</value>
        </row>
        <row>
            <value>000061</value>
            <value>Bolton</value>
            <value>Larry</value>
        </row>
        <row>
            <value>000092</value>
            <value>Hadley</value>
            <value>Charles</value>
        </row>
    </data>
</dataset>

每个节点代表什么在上一节中定义。也就是说,这是我想要的输出:

000056,Atkinson,Joan
000061,Bolton,Larry
000092,Hadley,Charles

这是我开始使用的 XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" omit-xml-declaration="yes" indent="no"/>
  <xsl:strip-space elements="*" />

  <xsl:template match="/data">
    <xsl:for-each select="row">
      <!-- Employee Number -->
      <xsl:text>,</xsl:text>
      <!-- Last Name -->
      <xsl:text>,</xsl:text>
      <!-- First Name -->
      <xsl:text>,</xsl:text>
      <!-- new line -->
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

我还没有想出如何正确地为三个数据元素中的每一个元素编码,所以我希望在三行输出中的每一行中实际上只看到两个逗号。然而,这是我实际得到的:

000056AtkinsonJoan000061BoltonLarry000092HadleyCharles

它忽略了 for-each 循环中的所有内容,只输出整个元素中的所有数据。我还发现,即使我将 select="row" 属性更改为 select="zzz"(或任何其他值),我仍然会得到相同的结果。那么,我在哪里离开了rails?

这是因为你有一个默认的命名空间。您看到的结果来自 built-in templates。您应该使用前缀声明名称空间并在您的 XPath 中使用该前缀。

示例...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:x="http://developer.cognos.com/schemas/xmldata/1/">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*" />

    <xsl:template match="x:row">
        <xsl:apply-templates/>
        <xsl:text>&#xA;</xsl:text>
    </xsl:template>

    <xsl:template match="x:value">
        <xsl:if test="not(position()=1)">
            <xsl:text>,</xsl:text>
        </xsl:if>
        <xsl:value-of select="."/>
    </xsl:template>
</xsl:stylesheet>

这是由输入中的附加命名空间引起的问题 XML

xmlns="http://developer.cognos.com/schemas/xmldata/1/"

您可以将带有前缀的命名空间添加到 XSLT,例如作为

xmlns:c="http://developer.cognos.com/schemas/xmldata/1/"

然后相应地匹配XML的元素:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:c="http://developer.cognos.com/schemas/xmldata/1/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" omit-xml-declaration="yes" indent="no"/>
<xsl:strip-space elements="*" />
   <xsl:template match="//c:data">
    <xsl:for-each select="c:row">
      <xsl:for-each select="c:value">
        <xsl:value-of select="."/>
        <xsl:if test="position() != last()">
          <xsl:text>,</xsl:text>
        </xsl:if>
      </xsl:for-each>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

输出:

000056,Atkinson,Joan
000061,Bolton,Larry
000092,Hadley,Charles

我为值添加了第二个 for-each 循环,否则您可以使用 <xsl:value-of select="c:value[1]"/> 检索第一个值等的值。

保存的例子:http://xsltransform.net/pPqsHTu