XSLT - 屏蔽数据 - 以其他标签为条件
Posted
技术标签:
【中文标题】XSLT - 屏蔽数据 - 以其他标签为条件【英文标题】:XSLT - masking data - Conditional on other tags 【发布时间】:2021-11-11 09:33:29 【问题描述】:我正在尝试屏蔽存在某些特定标签的 xml 文档。我创建了一个包含 saxon9he
作为依赖项的 java 应用程序。
<dependencies>
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>saxon9he</artifactId>
<version>9.4.0.4</version>
</dependency>
</dependencies>
我有多个用例,有些是直截了当的,但有些是有条件的。假设以下给定的<Prsn>
标签出现在多个不同的位置:
输入xml sn-p
<ns3:Prsn>
<ns3:FrstNm>BDMFN</ns3:FrstNm>
<ns3:Nm>BDMSN</ns3:Nm>
<ns3:BirthDt>2000-01-02</ns3:BirthDt>
<ns3:Othr>
<ns3:Id>GB1592102</ns3:Id>
<ns3:SchmeNm>
<ns3:Cd>CCPT</ns3:Cd>
</ns3:SchmeNm>
</ns3:Othr>
</ns3:Prsn>
需要的转换
在上面提供的 XML 中,我们需要屏蔽一些标签 [FrstNm、Nm、BirthDt](删除实际的来自这些标签的数据并用 # 替换每个字符),顺便说一句,到目前为止我已经实现了。
需要帮助
棘手的部分是当我们有标签 <Othr><SchmeNm><Cd>
可以有值 [NIND, CCPT, CONCAT] 时,我们需要屏蔽 <Othr><id>
,但除了 <Othr><SchmeNm><Cd>
中的任何其他值NIND、CCPT、CONCAT 然后<Othr><id>
没有变化。
Transformation.xsl
<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>
<xsl:template match="*[local-name()='FrstNm']">
<xsl:copy>
<xsl:value-of select="replace(text(), '[A-Za-z]','#')" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[local-name()='Nm']">
<xsl:copy>
<xsl:value-of select="replace(text(), '[A-Za-z]','#')" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[local-name()='BirthDt']">
<xsl:copy>
<xsl:value-of select="replace(text(), '[0-9]','#')" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
【问题讨论】:
XSLT 1.0 中不存在replace()
函数。
Saxon 9.4 很久以前了:当前版本是10.5
借助 Saxon,您可以使用 XSLT 2.0 语法 match="*:Nm"
【参考方案1】:
如果您想进行基于正则表达式的搜索和替换,您需要的最低 XSLT 版本是 XSLT 2.0。
另外,不要使用local-name()
。为命名空间 URI 注册一个前缀并使用它。前缀不必与 XML 文档匹配,只要命名空间 URI 相同即可。
输入:
<ns3:Prsn xmlns:ns3="some-namespace-uri">
<ns3:FrstNm>BDMFN</ns3:FrstNm>
<ns3:Nm>BDMSN</ns3:Nm>
<ns3:BirthDt>2000-01-02</ns3:BirthDt>
<ns3:Othr>
<ns3:Id>GB1592102</ns3:Id>
<ns3:SchmeNm>
<ns3:Cd>CCPT</ns3:Cd>
</ns3:SchmeNm>
</ns3:Othr>
</ns3:Prsn>
XSLT 2.0+:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:person="some-namespace-uri"
>
<xsl:output method="xml" indent="yes" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="person:FrstNm|person:Nm|person:BirthDt">
<xsl:copy>
<xsl:value-of select="replace(text(), '[A-Za-z0-9]', '#')" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出:
<ns3:Prsn xmlns:ns3="some-namespace-uri">
<ns3:FrstNm>#####</ns3:FrstNm>
<ns3:Nm>#####</ns3:Nm>
<ns3:BirthDt>####-##-##</ns3:BirthDt>
<ns3:Othr>
<ns3:Id>GB1592102</ns3:Id>
<ns3:SchmeNm>
<ns3:Cd>CCPT</ns3:Cd>
</ns3:SchmeNm>
</ns3:Othr>
</ns3:Prsn>
如果您只有 XSLT 1.0,您可以使用translate()
。但这要求您明确列出所有个可能的输入字符:
<xsl:template match="person:FrstNm|person:Nm|person:BirthDt">
<xsl:copy>
<xsl:value-of select="tanslate(
text(),
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-add-everything-else',
'##################################################################################'
)" />
</xsl:copy>
</xsl:template>
或者你选择更简单的东西:
<xsl:template match="person:FrstNm|person:Nm|person:BirthDt">
<xsl:copy>
<xsl:text>[redacted]</xsl:text>
</xsl:copy>
</xsl:template>
棘手的部分是当我们有标签
<Othr><SchmeNm><Cd>
,它可以有值[NIND,CCPT,CONCAT],我们需要屏蔽<Othr><id>
,但是<Othr><SchmeNm><Cd>
中的任何其他值除了NIND,CCPT,CONCAT然后没有更改<Othr><id>
。
这很容易。在 XSLT 1.0+ 这工作:
<xsl:template match="
person:FrstNm|person:Nm|person:BirthDt|person:Id[
../person:SchmeNm/person:Cd = 'NIND' or
../person:SchmeNm/person:Cd = 'CCPT' or
../person:SchmeNm/person:Cd = 'CONCAT'
]
">
甚至这个:
<xsl:template match="
person:FrstNm|person:Nm|person:BirthDt|person:Id[
contains('|NIND|CCPT|CONCAT|', concat('|', ../person:SchmeNm/person:Cd, '|'))
]
">
在 XSLT 2.0+ 中,您可以使用序列:
<xsl:template match="
person:FrstNm|person:Nm|person:BirthDt|person:Id[
../person:SchmeNm/person:Cd = ('NIND', 'CCPT', 'CONCAT')
]
">
【讨论】:
如果值为 NIND 或 CCPT 或 CONCAT,我想根据[a-zA-Z0-9]
更好的东西。 \w
运作良好,涵盖所有 Unicode 字母和数字。
另见:***.com/a/68407659/3016153以上是关于XSLT - 屏蔽数据 - 以其他标签为条件的主要内容,如果未能解决你的问题,请参考以下文章