XSLT - 屏蔽数据 - 以其他标签为条件 [英] XSLT - masking data - Conditional on other tags
问题描述
我试图掩盖存在某些特定标签的 xml 文档.我创建了一个包含 saxon9he
作为依赖项的 Java 应用程序.
<依赖><groupId>net.sf.saxon</groupId><artifactId>saxon9he</artifactId><version>9.4.0.4</version></依赖></依赖项>
我有多个用例,有些是直接的,但有些是有条件的.假设下面给定的
标签存在于多个不同的位置:
输入 xml 片段
<ns3:FrstNm>BDMFN</ns3:FrstNm><ns3:Nm>BDMSN</ns3:Nm><ns3:BirthDt>2000-01-02</ns3:BirthDt><ns3:其他><ns3:Id>GB1592102</ns3:Id><ns3:SchmeNm><ns3:Cd>CCPT</ns3:Cd></ns3:SchmeNm></ns3:Othr></ns3:Prsn>
需要的转型
在上面提供的 XML 中,我们有一些需要屏蔽的标签 [FrstNm, Nm, BirthDt](删除实际的来自这些标签的数据并用 # 替换每个字符),到目前为止我已经实现了这一点.
需要帮助
棘手的部分是当我们有标签
可以有值 [NIND, CCPT, CONCAT] 时,我们需要屏蔽
,但是
中除 NIND、CCPT、CONCAT 之外的任何其他值
没有变化.
转换.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/变换"><xsl:output method="xml" indent="yes"/><xsl:template match="@* | node()"><xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy></xsl:模板><xsl:template match="*[local-name()='FrstNm']"><xsl:copy><xsl:value-of select="replace(text(), '[A-Za-z]','#')"/></xsl:copy></xsl:模板><xsl:template match="*[local-name()='Nm']"><xsl:copy><xsl:value-of select="replace(text(), '[A-Za-z]','#')"/></xsl:copy></xsl:模板><xsl:template match="*[local-name()='BirthDt']"><xsl:copy><xsl:value-of select="replace(text(), '[0-9]','#')"/></xsl:copy></xsl:模板></xsl:stylesheet>
如果你想做基于正则表达式的搜索和替换,你需要的最低 XSLT 版本是 XSLT 2.0.
另外,不要使用local-name()
.为命名空间 URI 注册一个前缀并使用它.前缀不必与 XML 文档匹配,只要命名空间 URI 相同即可.
输入:
<ns3:FrstNm>BDMFN</ns3:FrstNm><ns3:Nm>BDMSN</ns3:Nm><ns3:BirthDt>2000-01-02</ns3:BirthDt><ns3:其他><ns3:Id>GB1592102</ns3:Id><ns3:SchmeNm><ns3:Cd>CCPT</ns3:Cd></ns3:SchmeNm></ns3:Othr></ns3:Prsn>
XSLT 2.0+:
<xsl:copy><xsl:apply-templates select="@* |节点()"/></xsl:copy></xsl:模板><xsl:template match="person:FrstNm|person:Nm|person:BirthDt"><xsl:copy><xsl:value-of select="replace(text(), '[A-Za-z0-9]', '#')";/></xsl:copy></xsl:模板></xsl:stylesheet>
输出:
<ns3:FrstNm>#####</ns3:FrstNm><ns3:Nm>#####</ns3:Nm><ns3:BirthDt>####-##-##</ns3:BirthDt><ns3:其他><ns3:Id>GB1592102</ns3:Id><ns3:SchmeNm><ns3:Cd>CCPT</ns3:Cd></ns3:SchmeNm></ns3:Othr></ns3:Prsn>
如果您只有 XSLT 1.0 可用,您可以使用 translate()
.但这要求您明确列出所有可能的输入字符:
<xsl:copy><xsl:value-of select="tanslate(文本(),'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-add-everything-else','##############################################################################)"/></xsl:copy></xsl:模板>
或者你选择更简单的东西:
<xsl:copy><xsl:text>[已编辑]</xsl:text></xsl:copy></xsl:模板>
<块引用>
棘手的部分是当我们有标签
可以有值 [NIND, CCPT, CONCAT] 时,我们需要屏蔽 <;Othr>
,但
中除 NIND、CCPT、CONCAT 之外的任何其他值则 没有变化;其他>
.
这很简单.在 XSLT 1.0+ 中这是有效的:
在 XSLT 2.0+ 中,您可以使用序列:
<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>
Transformation that is needed
In this above provided XML, we have some tags [FrstNm, Nm, BirthDt] which we need to mask (remove the actual data from these tags and replace with # for each character), which by the way I have achieved so far.
Need Help
Tricky part is when we have tag <Othr><SchmeNm><Cd>
which can have values [NIND, CCPT, CONCAT], we need to mask <Othr><id>
, but any other value in <Othr><SchmeNm><Cd>
apart from NIND, CCPT, CONCAT then no change in <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>
If you want to do regex-based search and replace, the minimum XSLT version you need is XSLT 2.0.
Also, don't use local-name()
. Register a prefix for the namespace URI and use that. The prefix does not have to match the XML document, as long as the namespace URI is the same.
Input:
<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>
Output:
<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>
If you only have XSLT 1.0 available, you can use translate()
. But that requires that you either explicitly list all possible input characters:
<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>
or that you settle on something simpler:
<xsl:template match="person:FrstNm|person:Nm|person:BirthDt">
<xsl:copy>
<xsl:text>[redacted]</xsl:text>
</xsl:copy>
</xsl:template>
Tricky part is when we have tag
<Othr><SchmeNm><Cd>
which can have values [NIND, CCPT, CONCAT], we need to mask<Othr><id>
, but any other value in<Othr><SchmeNm><Cd>
apart from NIND, CCPT, CONCAT then no change in<Othr><id>
.
That's easy. in XSLT 1.0+ this works:
<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'
]
">
or even this:
<xsl:template match="
person:FrstNm|person:Nm|person:BirthDt|person:Id[
contains('|NIND|CCPT|CONCAT|', concat('|', ../person:SchmeNm/person:Cd, '|'))
]
">
In XSLT 2.0+ you can use sequences:
<xsl:template match="
person:FrstNm|person:Nm|person:BirthDt|person:Id[
../person:SchmeNm/person:Cd = ('NIND', 'CCPT', 'CONCAT')
]
">
这篇关于XSLT - 屏蔽数据 - 以其他标签为条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!