使用 XSLT 重命名节点

2023-11-24

我正在尝试一些非常简单的事情,但由于某种原因它不起作用。基本上,我需要重命名 XML 文档中的一些节点。因此,我创建了一个 XSLT 文件来进行转换。

下面是 XML 的示例:

编辑:地址和地址元素出现在许多级别。这就是导致我不得不尝试应用 XSLT 的原因。 Visual Studio 类型化数据集功能(从 XSD 文件创建类型化数据集)不允许您对同一表进行嵌套引用。因此,拥有 Businesses/Business/Addresses 和 Businesses/Business/Contact/Addresses 会导致 Load() 失败。这是一个已知问题,他们告诉您的只是“没有嵌套表引用......编辑您的 XSD 以停止这种情况。”不幸的是,这意味着我们必须应用 XSLT 来使 XML 符合“被黑客攻击的”XSD,因为这些文件来自第三方供应商。

因此,我们非常接近这里提供的帮助。最后几件事是:

1.) 如何使用 xsl:template 的 match 属性中的命名空间引用来指定我要将 Businesses/Business/Addresses 重命名为 BusinessAddresses,但将 Businesses/Business/Contacts/Contact/Addresses 重命名为 ContactAddresses?

2.) 如何阻止 XSLT 使用显式名称空间引用来混淆每个新元素?它导致输出极度膨胀。

我创建了一个名为“steel”的命名空间,并取得了良好的成功:

<xsl:template match="steel:Addresses>
  <xsl:element name="BusinessAddresses>
</xsl:template>

这里明显的问题是它重命名ALL将 Addresses 元素添加到 BusinessAddresses,即使我希望其中一些元素命名为 ContactAddresses,依此类推。对所有重命名的节点不必要地添加显式名称空间引用也很麻烦。

我尝试了这种方法,但是一旦我向 match 属性添加斜杠,XSLT 中就会出现语法错误,如下所示:

<xsl:template match="steel:/Businesses/Business/Addresses">

我感觉非常接近,但需要一些关于如何混合命名空间使用和使用斜杠进行选择的方法的指导ANY特定路径下的节点。

<?xml version="1.0"?>
<Businesses>
  <Business>
    <BusinessName>Steel Stretching</BusinessName>
    <Addresses>
      <Address>
        <City>Pittsburgh</City>
      </Address>
      <Address>
        <City>Philadelphia</City>
      </Address>
    </Addresses>
    <Contacts>
      <Contact>
        <FirstName>Paul</FirstName>
        <LastName>Jones</LastName>
        <Addresses>
          <Address>
            <City>Pittsburgh</City>
          </Address>
        </Addresses>
      </Contact>
    </Contacts>
  </Business>
  <Business>
    <BusinessName>Iron Works</BusinessName>
    <Addresses>
      <Address>
        <City>Harrisburg</City>
      </Address>
      <Address>
        <City>Lancaster</City>
      </Address>
    </Addresses>
  </Business>
</Businesses>

我需要将地址重命名为 BusinessAddresses,并且需要将地址重命名为 BusinessAddress,对于直接位于业务节点下的地址和地址的每个实例。我还需要将 Addresses 重命名为 ContactAddresses,并且需要将 Addresses 重命名为 ContactAddress,对于直接位于 Contact Node 下的 Addresses 和 Address 的每个实例。

我尝试了几种解决方案,但似乎都不起作用。它们最终都会生成与原始文件相同的 XML。

这是我尝试过的示例:

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

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

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

已经在至少 6 种不同的风格中进行了尝试,并通过 VB.Net 中的 XSLT 调试器进行了单步调试。它从不执行地址的模板匹配。

Why?


为什么 XSLT 可能会失败?

XSLT 会因为拼写错误等明显问题而失败。然而,最有可能的情况与命名空间的使用有关。如果您为 XML 声明了默认名称空间,但未将其包含在 XSLT 中,则 XSLT 将不会像您期望的那样与模板匹配。

以下示例添加了xmlns:business属性,声明由以下条件限定的项目business前缀属于命名空间mynamespace.uri。然后,我使用此前缀来限定地址和地址模板匹配。当然,您需要将命名空间 URI 更改为与 XML 文件的默认命名空间相匹配的任何名称。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:business="mynamespace.uri"
                exclude-result-prefixes="msxsl">
  <xsl:template match="/">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:template>

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

  <xsl:template match="business:Addresses">
    <xsl:element name="BusinessAddresses">
      <xsl:apply-templates select="@*|node()" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="business:Address">
    <xsl:element name="BusinessAddress">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

如何根据元素位置和名称来匹配模板?

有多种方法可以解决您的问题的最后一部分,BusinessAddress 或 ContactAddress,但最简单的方法是修改模板match考虑父节点的属性。如果你想到match属性作为节点的 XML 路径,此选项变得更加清晰(为简洁起见,省略了模板的内容):

<xsl:template match="business:Business/business:Addresses>
</xsl:template>

<xsl:template match="business:Business/business:Addresses/business:Address">
</xsl:template>

<xsl:template match="business:Contact/business:Addresses">
</xsl:template>

<xsl:template match="business:Contact/business:Addresses/business:Address">
</xsl:template>

存在其他方法来实现这一点,如果match仍然仅基于元素名称,但它们更难实现、遵循和维护,因为它们涉及对正在处理的元素的父节点层次结构进行条件检查,所有这些都在模板内。

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

使用 XSLT 重命名节点 的相关文章

随机推荐

  • 简单的嵌套 for 循环示例

    目前我正在准备 Java 测试 在学习的过程中我遇到了一个小问题 在这个 for 循环中 for int i 1 i lt 3 i for int j 1 j lt 3 j System out println i j 输出是 1 1 1
  • 电子邮件中的 Google DFP 广告表现异常

    我正在尝试通过电子邮件投放 DFP 广告管理系统广告 我遵循指导方针here 我专门为电子邮件设置了一个广告单元 我有一个订单项定位到该广告单元 其中仅包含一个图片广告素材 该订单项没有任何定位限制或类似内容 广告将出现在电子邮件中 至少第
  • .NET Core SDK 版本 2.2.202 的 MSBuild 失败

    下载并安装 Visual Studio 2019 RC 后 我无法运行 msbuild 并收到以下错误 NET Core SDK 版本 2 2 202 至少需要 MSBuild 版本 16 0 0 MSBuild 当前可用的版本是 15 6
  • 如何向edittext添加文本

    我在填充编辑文本时遇到问题 使用以下代码我可以很好地设置文本 但是我想做的是添加到编辑文本中 例如 以下代码在我的编辑文本中显示 1 但如果我再次按下它 它只会将 1 替换为 1 依此类推 我需要的是如果我按四次它就会显示 1111 这是我
  • Cassandra - 合理的最大表数是多少?

    我是卡桑德拉的新手 据我了解 每个键空间可以存储的最大表数是 Integer Max Value 然而 如此大量的表从性能角度 速度 存储等 来看有何影响 对此有什么建议吗 虽然 Cassandra 中有大量表的合法用例 但这种情况很少见
  • 如何将 div 放在图像上?

    我试图在图像上放置一个 div 使其像标题一样直接位于图像之上 有时标题比其他时候长 所以我无法设置特定的 margin top px 因为有时标题的高度更长 我尝试了这个 链接的背景 黑色 没有显示 也像我刚才所说的那样 标题高度发生了变
  • Java 8:如何将 String 转换为 Map

    我有一张地图 Map
  • std::引用类型的可选特化

    Why std optional std experimental optional in libc 目前 没有针对引用类型的专门化 与boost optional 我认为这将是非常有用的选择 是否有一些对象参考maybe已经存在的对象中的
  • 如何结合锚点id进行分页

    我对 Ruby on Rails 非常陌生 在尝试修复公司网站上的一些错误时正在学习 我正在尝试对与特定锚点相结合的记录集合进行分页 即当用户单击下一页 上一页时 就会发生分页并且用户登陆页面的特定部分 这就是我的代码目前的样子 view
  • MSVC 中的分解

    如何在 MSVC 中取消名称解析 gcc中有abi cxa demangle函数 在 MSDN 中我发现了 UnDecorateSymbolName http msdn microsoft com ru ru library windows
  • 如何将多个 TFS 存储库拉入单个 Jenkins 作业中?

    我有一个仓库 有 2 个子文件夹 Repo project 和 Repo thirdparty 我需要将这两个都拉到 Jenkins 中进行单个构建 当然 我尝试只拉动 Repo 但这给了我一堆其他项目以及错误的民意调查 每次将任何东西签入
  • 如何在 R 和 ggplot2 中将绘图拟合到背景图像上

    我正在尝试适应背景图像上显示的绘图 由于清晰度的损失 我无法将图像拉伸太多 因此 我必须将绘图放在比绘图薄得多的背景图像上 我不知道怎么做 请参阅附图 这是示例 R 代码 library ggplot2 library readxl lib
  • React-Native:从 Firebase 存储下载图像

    预先信息 我仍然打开了一个 Firebase 项目 并且我仍然成功地使用 Firebase 数据库 So the firebase initializeApp config works 我在我的 Firebase Storage 文件夹中上
  • 仅从 JavaScript 中的 JSON 对象中提取值,而不使用循环

    有没有一种 很好 的方法可以从 json 对象中获取所有值 我不关心键 只需将值放入数组中 不使用循环 lang 是 JavaScript 这取决于你如何定义 循环 您可以使用以下命令提取属性Object keys进而map他们遵循自己的价
  • 将数据从堆栈溢出查询导入到 R 中的代码

    当我尝试回答 Stack Overflow 中有关 R 的问题时 我的大部分时间都花在尝试重建示例中给出的数据 除非问题作者足够好地将它们作为 R 代码提供 所以我的问题是 如果有人只是问一个问题并按以下方式给出他的样本数据框 a b c
  • 如何确定 macOS 10.14 强调色?

    MacOS 10 14 Mojave 具有深色界面风格和用户可选择的颜色强调 如何读取这些值并监听变化 编辑 现在 macOS 11 推出了具有自己独特配色方案的新 M1 iMac 我可以使用这样的 iMac 但无法确定强调色 它是黄色版本
  • 为什么默认参数构造函数被称为默认构造函数

    Class A public A int i 0 int k 0 default constructor WHY A int main A a This creates object using defined default constr
  • 使用R通过ggplot计算重叠密度图的面积

    如何获得重叠密度曲线下的面积 如何用R解决这个问题 这里有一个python的解决方案 计算两个函数的重叠面积 set seed 1234 df lt data frame sex factor rep c F M each 200 weig
  • nltk斯坦福NERTagger:如何获得不大写的专有名词

    我正在尝试使用斯坦福NERTagger 和nltk 从一段文本中提取关键字 docText John Donk works for POI Brian Jones wants to meet with Xyz Corp for measur
  • 使用 XSLT 重命名节点

    我正在尝试一些非常简单的事情 但由于某种原因它不起作用 基本上 我需要重命名 XML 文档中的一些节点 因此 我创建了一个 XSLT 文件来进行转换 下面是 XML 的示例 编辑 地址和地址元素出现在许多级别 这就是导致我不得不尝试应用 X