XSLT 仅当元素不存在时插入元素

2024-04-21

我有一个源文件:

<?xml version="1.0"?>
<source>
  <ItemNotSubstituted/>
  <ItemToBeSubstituted Id='MatchId' />
</source>

以及包含我想要替换到源中的内容的样式表:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="xml" omit-xml-declaration="no" version="1.0"/>
  <xsl:preserve-space elements="//*"/>

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

  <xsl:template match="ItemToBeSubstituted[@Id = 'MatchId']">
    <xsl:copy>
      <xsl:copy-of select="@*|*"/>
      <Element1/>
      <Element2 Value="foo"/>
      <Element3 Value="bar"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

此样式表已成功复制<Element1/><Element2 Value="foo"/><Element3 Value="bar"/> into ItemToBeSubstituted。但是当我使用不同的源文档时,其中ItemToBeSubstituted已有内容:

<?xml version="1.0"?>
<source>
  <ItemNotSubstituted/>
  <ItemToBeSubstituted Id='MatchId'>
    <Element3 Value="baz"/>
  </ItemToBeSubstituted>
</source>

我得到这个输出:

<?xml version="1.0"?>
<source>
  <ItemNotSubstituted/>
  <ItemToBeSubstituted Id="MatchId">
    <Element3 Value="baz"/>
    <Element1/>
    <Element2 Value="foo"/>
    <Element3 Value="bar"/>
  </ItemToBeSubstituted>
</source>

我只想替换样式表中源文档中尚不存在的元素。这是将样式表应用于第二个文档后我正在寻找的输出,仅包含<Element3>源文档中的元素:

<?xml version="1.0"?>
<source>
  <ItemNotSubstituted/>
  <ItemToBeSubstituted Id="MatchId">
    <Element3 Value="baz"/>
    <Element1/>
    <Element2 Value="foo"/>
  </ItemToBeSubstituted>
</source>

使用 XSL 执行此操作的最佳方法是什么?样式表可能包含许多要替换的元素。所以我不想使用需要<xsl:if>围绕每一个元素。有没有比使用一个样式表插入内容,然后使用第二个样式表删除重复元素更好的方法?


此 XSLT 1.0 解决方案可实现您的预​​期:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:subst="http://tempuri.org/mysubst"
>

  <!-- expand this section to contain all your default elements/values -->
  <subst:defaults>
    <subst:element name="ItemToBeSubstituted" id="MatchId">
      <subst:Element1/>
      <subst:Element2 Value="foo"/>
      <subst:Element3 Value="bar"/>
    </subst:element>
  </subst:defaults>

  <!-- this makes the above available as a variable -->
  <xsl:variable name="defaults" select="document('')/*/subst:defaults" />

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

  <!-- expand the match expression to contain all elements 
       names that need default values -->
  <xsl:template match="ItemToBeSubstituted">
    <xsl:copy>
      <xsl:copy-of select="@*|*"/>
      <xsl:call-template name="create-defaults" />
    </xsl:copy>
  </xsl:template>

  <!-- this does all the heavy lifting -->
  <xsl:template name="create-defaults">
    <xsl:variable name="this" select="." />

    <xsl:for-each select="
      $defaults/subst:element[@name = name($this) and @id = $this/@Id]/*
    ">
      <xsl:if test="not($this/*[name() = local-name(current())])">
        <xsl:apply-templates select="." />
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <!-- create the default nodes without namespaces -->
  <xsl:template match="subst:*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="subst:*|@*" />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

使用单独的命名空间(“subst”)使您能够在样式表中保留默认值。这是否是一件好事取决于,至少你不必有两个文件。

如果您希望样式表与默认值分离,请将它们放入额外的文件中并使用此行。

<xsl:variable name="defaults" select="document('defaults.xml')/subst:defaults" />

一旦执行此操作,您就可以放弃所有额外的命名空间处理,并最终或多或少地得到 Josh Davis 提出的解决方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XSLT 仅当元素不存在时插入元素 的相关文章

  • 用于冒号分隔标签的 XML 解析器? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 WSDL 中包含 XSD

    我正在编写一个 wsdl 文件来在未来 SoapUI 中部署模拟服务 但我在包含我的 xsd 文件时遇到问题 XSD File
  • 在工具栏下显示内容

    您好 我试图简单地将我的内容放在工具栏下方 但是当我运行我的应用程序时 某些内容本应位于工具栏下方 却隐藏在工具栏后面 我已经阅读了有关使用框架布局来尝试将其分离的内容 但我有点卡住了 我目前正在使用该软件提供的基本 android stu
  • JAXB - 忽略元素

    有什么方法可以忽略 Jaxb 解析中的元素吗 我有一个很大的 XML 文件 如果我可以忽略其中一个大而复杂的元素 那么它的解析速度可能会快很多 如果它根本无法验证元素内容并解析文档的其余部分 即使该元素不正确 那就更好了 例如 这应该只生成
  • 文本视图不显示全文

    我正在使用 TableLayout 和 TableRow 创建一个简单的布局 其中包含两个 TextView 这是代码的一部分
  • 具有多个应用程序标签的 AndroidManifest.xml

    我对 Android 编程非常陌生 我一直在试图找出为什么我的应用程序在单击按钮时强制关闭 我已将范围缩小到几件事 一个问题 是否可以拥有多个
  • 将 XML 映射到 C# 中的类

    我希望使用 XmlSerializer 对象将嵌套元素中的多个 XML 属性映射到单个 POCO 类中 XML
  • 为什么 XPath 不能与 xmlns 属性一起使用

    我有以下 XPath 表达式 configuration properties 这是我的 XML
  • PHP 和 DOM 文档

    我有一个关于 DOMDocument 的使用和创建 XML 的问题 我有一个 PHP 程序 加载到 XML 文件中 处理XML的每个节点 行 将其发送到另一个进程 然后该进程返回一个 XML 元素 我获取节点的字符串表示形式 以便可以创建
  • 主题以编程方式设置。如何重新加载 Activity 来应用

    如何在不重新启动整个应用程序的情况下应用主题 如果我这样做startActivity getIntent finish 活动退出并且不重新启动 是否可以简单地重新启动 重新创建活动来应用主题 它的顺序不正确 finish intent ne
  • 根据属性值使用 xslt 合并两个元素

    这是我的源文件的样子
  • 检查 XML 元素是否存在

    如何验证 XML 文件中是否存在特定元素 假设我有一个不断变化的 XML 文件 我需要在读取 解析它之前验证每个元素是否存在 if doc SelectSingleNode mynode null 应该这样做 显然 其中 doc 是您的 X
  • 在 Java 中创建 XML 文件的最佳方法是什么?

    我们目前使用 dom4j 来创建 XML 文件 不过 我猜现在有更好的东西了 如果我们使用的是 Java 1 6 或更高版本 那么在编写 XML 文件时最好使用什么类 运行速度最快 使用简单 我不需要构建一个 DOM 然后编写整个 DOM
  • 将 transaction.commit_manually() 升级到 Django > 1.6

    我继承了为 Django 1 4 编写的应用程序的一些代码 我们需要更新代码库以使用 Django 1 7 并最终更新到 1 8 作为下一个长期支持版本 在一些地方它使用旧风格 transaction commit manually and
  • 单元测试报告的 XML 格式规范(DTD、XSD..)

    许多工具为单元测试报告生成和使用相同的 XML 文件格式 例子 source http junitpdfreport cvs sourceforge net junitpdfreport src resources examples tes
  • 删除Android所有语言中的字符串

    我有一个包含多个翻译的应用程序 我想删除一些字符串 我怎样才能重构并删除它们一次 例如在默认情况下strings xml文件并自动将删除传播到其他翻译的其他 strings xml 文件 您可以通过 Android Studio 中的 翻译
  • 如何在 Spring 属性中进行算术运算?

  • 如何在Android中解析xml类型的HTTPResponse

    我有一个 Android 应用程序 我使用 POST 方法来获取响应 这是我的代码 HttpResponse httpResponse httpclient execute httppost HttpEntity resEntity htt
  • XSL字符串多重替换功能

    如何让这个函数进行多重替换 经验 替换aaa with 111并替换bbb with 222 etc
  • dbms_xmlgen.getxml - 如何设置日期格式

    我们使用 dbms xmlgen getxml 实用程序通过 SQL 查询生成 xml 该查询从几乎 10 15 个相关表中获取数据 默认情况下 日期格式生成于dd MMM yy格式 有什么方法可以在 dbms xmlgen getxml

随机推荐