当前位置: 首页 > 知识库问答 >
问题:

CDATA使用XSLT屏蔽XML应该返回相同的XML,但屏蔽字段很少

葛雨华
2023-03-14

我需要用XSLT在XML中屏蔽CDATA的XML中的几个字段
因此,结果XML应该与输入XML相同,但很少有文件被XSLT屏蔽
我遵循了这个链接,它按照预期屏蔽了XML,但生成XML的格式不同
我尝试了许多其他解决方案,因此,他们几乎是以其他格式输出新的XML/HTML,这与输入XML不同
为了更好地理解,请查看以下示例
输入包含CDATA内容的XML。

<XML>
  <LogLevel>info</LogLevel>
  <Content><![CDATA[ <Msg>
        <AccountNo>2701000098983</AccountNo>
        <ApplName>Testing</ApplName>
       </Msg>]]></Content>
  <Date>20140909</Date>
</XML>

输出XML应为:

   <XML>
      <LogLevel>info</LogLevel>
      <Content><![CDATA[ <Msg>
            <AccountNo>XXXXXXXXXX983</AccountNo>
            <ApplName>Testing</ApplName>
           </Msg>]]></Content>
      <Date>20140909</Date>
   </XML>

编辑:
我使用了以下XSLT

 <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
    <xsl:template match="text()">
        <xsl:choose>
            <xsl:when test="contains(.,'&lt;AccountNo&gt;')">
                <!-- This is the CDATA that I want to mask and write back out as CDATA -->
                <xsl:variable name="tcontent">
                    <xsl:value-of
                        select="substring-after(substring-before(.,'&lt;/AccountNo&gt;'),'&lt;AccountNo&gt;') " />
                </xsl:variable>
                <xsl:text disable-output-escaping="yes">&lt;![CDATA[&lt;AccountNo&gt;</xsl:text>
                <xsl:call-template name="maskVariable">
                    <xsl:with-param name="tvar" select="$tcontent" />
                </xsl:call-template>
                <xsl:text disable-output-escaping="yes">&lt;/AccountNo&gt;]]&gt;</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
<xsl:template name="maskVariable">
    <xsl:param name="tvar" />
    <xsl:variable name="length" select="string-length($tvar)" />
    <xsl:choose>
        <xsl:when test="$length > 3">
            <xsl:value-of
                select="concat ('************', substring($tvar,$length - 1, 2))" />
        </xsl:when>
        <xsl:when test="$length > 1">
                ***
            </xsl:when>
            <xsl:otherwise />
        </xsl:choose>
    </xsl:template>

使用此XSLT的输出是:

<LogLevel>info</LogLevel>
<Content><![CDATA[<AccountNo>************02</AccountNo>]]></Content>
<Date>20140909</Date>

在输出中,仅显示的屏蔽输出
如何显示代码的其他部分?请告诉我怎么做<非常感谢您的帮助。

共有2个答案

蒯硕
2023-03-14

CDATA部分中的内容是伪装成文本的XML。XSLT擅长转换XML,但不擅长转换文本,尤其是语法复杂的文本。因此,我的方法是:从外部XML文档中提取文本,将其解析为XML,使用XSLT(在节点而不是标记上工作的真正XSLT)进行转换,将其序列化回文本,然后将文本填充回原始(外部)XML文档。

Raw XSLT1.0不能在单个样式表中做到这一点。您需要函数parse()和序列化()将词汇XML转换成节点树,然后再转换回来。这些函数在一些处理器(如Saxon)中作为扩展可用,在XPath 3.0中作为标准函数可用,在大多数其他处理器中可以作为简单的扩展函数(如Javascript)代码编写。

戚俊美
2023-03-14

你为什么不试试:

XSLT1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="Content">
    <xsl:copy>
        <xsl:value-of select="substring-before(.,'&lt;AccountNo&gt;')" />
        <xsl:text>&lt;AccountNo&gt;</xsl:text>
        <xsl:variable name="acct-num" select="substring-before(substring-after(.,'&lt;AccountNo&gt;'), '&lt;/AccountNo&gt;')" />
        <xsl:value-of select="concat('************', substring($acct-num, string-length($acct-num) - 2))" />
        <xsl:text>&lt;/AccountNo&gt;</xsl:text>
        <xsl:value-of select="substring-after(.,'&lt;/AccountNo&gt;')" />
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

应用于您的输入,结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<XML>
   <LogLevel>info</LogLevel>
   <Content> &lt;Msg&gt;
        &lt;AccountNo&gt;************983&lt;/AccountNo&gt;
        &lt;ApplName&gt;Testing&lt;/ApplName&gt;
       &lt;/Msg&gt;</Content>
   <Date>20140909</Date>
</XML>

或者,您可以使用:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" cdata-section-elements="Content"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="Content">
    <xsl:copy>
        <xsl:variable name="content">
            <xsl:value-of select="substring-before(.,'&lt;AccountNo&gt;')" />
            <xsl:text>&lt;AccountNo&gt;</xsl:text>
            <xsl:variable name="acct-num" select="substring-before(substring-after(.,'&lt;AccountNo&gt;'), '&lt;/AccountNo&gt;')" />
            <xsl:value-of select="concat('************', substring($acct-num, string-length($acct-num) - 2))" />
            <xsl:text>&lt;/AccountNo&gt;</xsl:text>
            <xsl:value-of select="substring-after(.,'&lt;/AccountNo&gt;')" />
        </xsl:variable>
        <xsl:value-of select="$content" disable-output-escaping="yes"/> 
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

制作:

<?xml version="1.0" encoding="UTF-8"?>
<XML>
<LogLevel>info</LogLevel>
<Content><![CDATA[ <Msg>
        <AccountNo>************983</AccountNo>
        <ApplName>Testing</ApplName>
       </Msg>]]></Content>
<Date>20140909</Date>
</XML>

虽然这可能不适用于所有处理器(经测试可用于Xalan 2.7.1:http://xsltransform.net/jyH9rMk).

 类似资料:
  • 屏蔽IP 可以在此设置屏蔽蜘蛛爬的IP,点击右上角添加需要屏蔽的IP即可

  • 我使用的是javafx文本字段。我需要输入与格式##########匹配的数字和小数### 小数不可编辑,数字可以是任意数字;不允许其他输入。并非所有数字占位符都需要填写,例如,它可能是1.2或2.22.1,甚至是1.222.222.0 我尝试使用模式匹配与正则表达式来验证更改的文本,但仅此而已;它验证输入,它不会使十进制字段成为不可编辑的字段,并且工具提示不是一个选项。我不确定还能尝试什么。 我

  • 告警屏蔽页面可以查看所有被屏蔽的告警。 告警屏蔽页面可以查看所有被屏蔽的告警,支持解除屏蔽的功能。 入口:在云管平台单击左上角导航菜单,在弹出的左侧菜单栏中单击 “监控/告警/告警屏蔽” 菜单项,进入告警屏蔽页面。 查看被屏蔽的告警 该功能用于查看被屏蔽的告警记录。被屏蔽的告警将不会向用户发送告警消息。 在告警屏蔽页面,查看被屏蔽的告警记录。 支持查看以下信息: 策略名称:触发告警的资源匹配的告警

  • 点击屏蔽,该视频将被屏蔽不可播放。 点击恢复可恢复正常播放状态。

  • 问题内容: 当前,我们通常记录所有进出我们系统的XML文档,其中一些包含明文密码。我们希望能够配置执行此操作的logback logger / appender进行某种模式匹配或类似操作,并且如果它检测到存在替换它的密码(很可能带有星号)。注意,我们不想过滤掉日志条目,我们想掩盖其中的一部分。我很乐意提供有关如何通过注销执行此操作的建议。谢谢。 问题答案: 0.9.27版本的logback引入了替

  • 我有一个数组,我想屏蔽它,这样我就可以保持它的形状,即,不删除屏蔽的元素。 例如在此代码中 打印输入是对未屏蔽元素进行上述数学运算的结果,并返回一个没有屏蔽元素的1D数组。