使用XSLT添加和删除XML元素

时间:2013-05-22 16:02:08

标签: xslt xslt-1.0

我有一个XML文档,其中包含有关父实体的用户定义信息。我想创建一个XSLT来将XML转换为当前用户定义的列表。 XSLT将需要忽略已删除的元素,添加新元素,并保持用户定义的元素顺序。

示例输入XML:

    <InventoryProperties>
      <InvProp Name="Weight"
               Type="Text"
               Alignment="Right">12500</InvProp>
      <InvProp Name="Length"
               Type="Text"
               Alignemnt="Right">20.2</InvProp>
      <InvProp Name="GVW"
               Type="Text"></InvProp>
   </InventoryProperties>

所以现在用户已经更改了收集的数据点,并且不再需要GVW,但是在权重和长度之间添加了高度。到目前为止我所做的是获取我想要的元素并留下我不再需要的元素:

<xsl:apply-templates select="InventoryProperties/InvProp[@Name = 'Weight']"/>

重复当前定义的每个字段。这工作正常,并按预期保持顺序。为了添加新元素,我正在尝试这样的事情:

<xsl:apply-templates  select="InventoryProperties[not(InvProp[@Name='Height'])]"/>
 <xsl:template name="HeightTemplate"
                match="InventoryProperties[not(InvProp[@Name='Height'])]">

    <xsl:apply-templates select="@*[not(name()='Height')]|node()"/>

    <Property LabelText="HelloWorld" />
  </xsl:template>

以及其他几个版本,但没有任何东西可以产生我想要的东西:

<InventoryProperties>
  <Property LabelText="Weight"
            ControlType="Text">12500</Property>
  <Property LabelText="Height"
            ControlType="Text"></Property>
  <Property LabelText="Length"
            ControlType="Text">20.2</Property>
</InventoryProperties>

没有理由更改元素和属性名称,我只是试图分析工作中的内容和不起作用的内容。

2 个答案:

答案 0 :(得分:0)

我建议您为要添加到输出的每个字段名称调用命名模板。该命名模板将检查是否存在具有给定Name属性的元素,如果存在则复制它,如果没有,则创建具有正确属性的存根。

这显示了这个想法

<xsl:template match="InventoryProperties">
  <xsl:call-template name="inv-prop">
    <xsl:with-param name="name" select="'Weight'"/>
  </xsl:call-template>
  <xsl:call-template name="inv-prop">
    <xsl:with-param name="name" select="'Height'"/>
  </xsl:call-template>
  <xsl:call-template name="inv-prop">
    <xsl:with-param name="name" select="'Length'"/>
  </xsl:call-template>
</xsl:template>

<xsl:template name="inv-prop">
  <xsl:param name="name"/>
  <xsl:variable name="selection" select="InvProp[@Name = $name]"/>
  <xsl:choose>
    <xsl:when test="$selection">
      <xsl:copy-of select="$selection"/>
    </xsl:when>
    <xsl:otherwise>
      <InvProp Name="{$name}" Type="Text" Alignment="Right">
        <xsl:value-of select="InvProp[@Name = $name]"/>
      </InvProp>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<强>输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <InvProp Name="Weight" Type="Text" Alignment="Right">12500</InvProp>
   <InvProp Name="Height" Type="Text" Alignment="Right"/>
   <InvProp Name="Length" Type="Text" Alignemnt="Right">20.2</InvProp>
</root>

答案 1 :(得分:0)

也许你应该试一试 使用一些钩子忽略或添加元素身份转换

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

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <!-- ingnore not wonted stuff -->
    <xsl:template match ="InvProp[@Name='GVW'] " />

    <!-- add missing stuff -->
    <xsl:template match ="InvProp[@Name='Weight'] ">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
        <xsl:if test="not(following-sibling::InvProp[@Name='Height'])" >
            <InvProp Name="Height" Type="Text" Alignment="Right"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>