XSLT:仅替换模板中元素的某些子节点,另一方面替换apply-templates

时间:2015-03-10 07:11:29

标签: xml templates xslt

我必须将XML转换为另一种XML,我目前只是一个小问题: 在我的XSLT中,我匹配一个项目,我替换了它的一些子元素,我希望其余部分被apply-template替换。

示例:

使用此输入:

<?xml version="1.0" encoding="utf-8"?>
<ConfigurationNodes>
   <Versions>
      <PackagesA Version="1.8" />
      <PackageB Version="1.1" />
      <PackageC Version="1.7" />
   </Versions>
   <ConfigurationNode  Type="SomeSpecialType">
      <Name>MyName</Name>
      <Revision>0</Revision>
      <Description >The big full description here</Description>
      <Status Type="SpecialType2">
        <Value>Normal</Value>
        <Severity>255</Severity>
      </Status>
   </ConfigurationNode>
</ConfigurationNodes>

我想以此结束:

<?xml version="1.0" encoding="utf-8"?>
<ConfigurationNodes>
   <Versions>
      <PackagesA Version="1.8" />
      <PackageB Version="1.1" />
      <PackageC Version="1.7" />
   </Versions>
   <Object Name="Configuration" NodeType="SomeOtherType">
      <Property Name="Name" Value="MyName" Type="System.String" />
      <Property Name="Description" Value="The big full description here" Type="System.String" />
      <Property Name="Revision" Value="0" Type="System.Int32" />
      <Object Name="Status" Type="SomeOtherSpecialType2">
         <Property Name="Value" Value="Normal" Type="System.String" />
         <Property Name="Severity" Value="255" Type="System.Int32" />
      </Object>
   </Object>
</ConfigurationNodes>

目前我有这个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" indent="yes" />

  <xsl:template match="*[@Type='SomeSpecialType']">
    <Object Name="Configuration" NodeType="SomeOtherType">
      <Property Name="Name" Value="{Name/text()}" Type="System.String"/>
      <Property Name="Description" Value="{Description/text()}" Type="System.String"/>
      <Property Name="Revision" Value="{Revision/text()}" Type="System.Int32" />
      <xsl:apply-templates select="Status"/>
    </Object>
  </xsl:template>

  <xsl:template match="*[@Type='SpecialType2']">
    <Object Name="Status" Type="SomeOtherSpecialType2">
      <Property Name="Value" Value="Normal" Type="System.String"  />
      <Property Name="Severity" Value="255" Type="System.Int32"  />
    </Object>
  </xsl:template>

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

返回给我:

<?xml version="1.0" encoding="utf-8"?>
<ConfigurationNodes>
   <Versions>
      <PackagesA Version="1.8" />
      <PackageB Version="1.1" />
      <PackageC Version="1.7" />
   </Versions>
   <Object Name="Configuration" NodeType="SomeOtherType">
   <Property Name="Name" Value="MyName" Type="System.String" />
   <Property Name="Description" Value="The big full description here" Type="System.String" />
   <Property Name="Revision" Value="0" Type="System.Int32" />
   <Name>MyName</Name>
   <Revision>0</Revision>
   <Description>The big full description here</Description>
   <Object Name="Status" Type="SomeOtherSpecialType2">
      <Property Name="Value" Value="Normal" Type="System.String" />
      <Property Name="Severity" Value="255" Type="System.Int32" /></Object>
   </Object>
</ConfigurationNodes>

因此第一个模板中使用的元素仍然被复制(因为我猜它们不匹配)。

我也知道我可以放<xsl:apply-templates select="Status"/>,这会给我预期的结果,但在我未来的实际案例中,我希望所有不匹配的子元素根据其类型检查另一个模板。

有可能吗?

1 个答案:

答案 0 :(得分:0)

尝试制作第一个模板:

<xsl:template match="*[@Type='SomeSpecialType']">
    <Object Name="Configuration" NodeType="SomeOtherType">
        <Property Name="Name" Value="{Name}" Type="System.String"/>
        <Property Name="Description" Value="{Description}" Type="System.String"/>
        <Property Name="Revision" Value="{Revision}" Type="System.Int32" />
        <xsl:apply-templates select="*[not(self::Name or self::Description or self::Revision)]"/>
    </Object>
</xsl:template>

这会将模板应用于当前元素的所有子元素,除了那些已经明确用于填充属性的元素。


编辑:

  

我更期待一种我不必指定所有内容的方式   元素

然后我建议你这样试试:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="*[@Type='SomeSpecialType']">
    <Object Name="Configuration" NodeType="SomeOtherType">
        <xsl:apply-templates/>
    </Object>
</xsl:template>

<xsl:template match="*[@Type='SpecialType2']">
    <Object Name="Status" Type="SomeOtherSpecialType2">
        <Property Name="Value" Value="Normal" Type="System.String"  />
        <Property Name="Severity" Value="255" Type="System.Int32"  />
    </Object>
</xsl:template>

<xsl:template match="Name | Description">
    <Property Name="{name()}" Value="{.}" Type="System.String"/>
</xsl:template>

<xsl:template match="Revision">
    <Property Name="Revision" Value="{.}" Type="System.Int32"/>
</xsl:template>

</xsl:stylesheet>