【发布时间】:2023-04-04 23:37:01
【问题描述】:
我正在尝试一些非常简单的方法,但由于某种原因它不起作用。基本上,我需要重命名 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联系地址?
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>
对于直接在业务节点下的地址和地址的每个实例,我需要将地址重命名为业务地址,并且我需要将地址重命名为业务地址。我还需要将地址重命名为 ContactAddresses,并且我需要将地址重命名为 ContactAddress,对于直接在联系人节点下的地址和地址的每个实例。
我尝试了几种解决方案,但似乎都没有奏效。它们最终都会生成与原始文件相同的 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 调试器。它从不执行地址的模板匹配。
为什么?
【问题讨论】:
-
我在下面给出了答案,但我不确定它是否有帮助。会不会是正在处理的 XML 在标签名称中有拼写错误?我不确定还有什么建议 - 可以提供更多细节吗?
-
命名空间问题如何?也许您已经在输入 XML 文档中声明了默认命名空间,但没有在 XSLT 中使用所需的前缀声明它?