0

我想更改此代码

<?xml version="1.0" encoding="UTF-8"?>
  <xml>
    <file id="Tokw" cast="ind">
            <name>Token wst</name>
        <package>b_3</package>
        <package>c_5</package>
    </file>
    <file id="strlin" cast="bac">
            <name>str line</name>
        <package>b_2</package>
        <package>c_5</package>
            <package>a_2</package>
    </file>

依此类推,到此代码:

<md_db>
  <ID>1</ID>                        //auto numeration
  <file_id>Tokw</package_id>
  <cast>ind</cast>
  <name>Token wst</name>
  <package>b_3 c_5</package>
</md_db>
<md_db>
  <ID>2</ID>
  <file_id>stlin</file_id>
  <cast>bac</cast>
  <name>str line</name>
  <package>b_2 c_5 a_2</package>
</md_db>

什么 xsl 用来更改这个 XML 文件?它正在分解第一行文件 id,如果有包,它必须将它们收集到一个节点包中。还有一个 ID 不必自动编号,但必须有一个数字。

我还有这个代码:

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

    <xsl:template match="xml">
        <md_db>
            <ID></ID>
            <file><xsl:value-of select="file id"/></file>
        <cat><xsl:value-of select="cat"/></cat>
            <name><xsl:value-of select="name"/></name>
        <xsl:if test="package">
            <package><xsl:value-of select="package"/></package>
        </xsl:if>
        </md_db>
    </xsl:template>
</xsl:stylesheet>
4

1 回答 1

2

通常,在此类问题中,您将从身份模板开始。

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

就其本身而言,它只是按原样复制节点,然后您只需为确实需要更改的节点编写模板。在您的情况下,它几乎是所有这些,但仍然值得使用。

因此,例如,要将文件元素转换为md_db元素,模板将看起来像这样

  <xsl:template match="file">
    <md_db>
      <ID><xsl:number /></ID>
      <xsl:apply-templates select="@*|node()"/>
    </md_db>
  </xsl:template>

(注意使用xsl:number进行枚举)

要将file元素上的id属性转换为file_id元素,您可以这样做:

  <xsl:template match="file/@id">
    <file_id>
      <xsl:value-of select="."/>
    </file_id>
  </xsl:template>

至于元素,你可以有一个模板只匹配第一个元素

  <xsl:template match="package[1]">

看起来您正在使用 XSLT 2.0,在这种情况下,您可以很容易地输出当前和后续元素

    <package>
      <xsl:value-of select=".|following-sibling::package" separator=" "/>
    </package>

所有其他需要的是另一个模板来阻止身份转换拾取以下包元素并输出两次:

  <xsl:template match="package"/>

请注意,XSLT 将优先考虑两个模板可能匹配同一个节点的更具体的模板。

试试这个 XSLT:

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

  <xsl:template match="xml">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:template>

  <xsl:template match="file">
    <md_db>
      <ID><xsl:number /></ID>
      <xsl:apply-templates select="@*|node()"/>
    </md_db>
  </xsl:template>

  <xsl:template match="file/@cast">
    <cast>
      <xsl:value-of select="."/>
    </cast>
  </xsl:template>

  <xsl:template match="file/@id">
    <file_id>
      <xsl:value-of select="."/>
    </file_id>
  </xsl:template>

  <xsl:template match="package[1]">
    <package>
      <xsl:value-of select=".|following-sibling::package" separator=" "/>
    </package>
  </xsl:template>

  <xsl:template match="package"/>

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

编辑:如果您不能使用 XSLT 2.0,您可以将Package[1]模板更改为使用简单的xsl:for-each代替:

  <xsl:template match="package[1]">
    <package>
      <xsl:value-of select="."/>
      <xsl:for-each select="following-sibling::package">
        <xsl:value-of select="concat(' ', .)"/>
      </xsl:for-each>
    </package>
  </xsl:template>
于 2014-05-17T14:25:45.337 回答