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"/>,这将给我预期的结果,但在我未来的真实情况下,我希望所有不匹配的子元素都根据它们的类型检查另一个模板。

可能吗?

尝试制作您的第一个模板:

<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>

最新更新