XSLT - 屏蔽数据 - 以其他标签为条件 [英] XSLT - masking data - Conditional on other tags

查看:24
本文介绍了XSLT - 屏蔽数据 - 以其他标签为条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图掩盖存在某些特定标签的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆