我有一个棘手的问题。我需要对大量 xml 文件(超过 500 个)进行微小更改。更改涉及将值从“false”更改为“true”。需要更改的行如下所示:
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
而且它需要变成:
<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>
不幸的是,每个文件中都有很多这组标签的实例,所以我们无法进行简单的查找和替换。这组标签的独特之处在于它们出现在以下几行之后:
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
但是,每个文件都有不同的项目名称,所以我使用通配符将它们过滤掉。
<CID>.*BUS..*.DKV</CID>
问题是,CID 部分和需要更改的行之间的行数在各个文件中不一致。我需要找到一种方法来将中间的行通配符掉,并替换 Size 行。
有什么想法吗?我已经尝试过了:
<CID>.*BUS..*.DKV</CID>.*?<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>
但不知为何,这个方法没有奏效。提前谢谢您!
编辑以回应评论:
基本上我想说的是代码如下所示:
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
代码中的其他部分如下所示:
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
在代码中的其他地方。所以我使用 CID .BUS .DKV 行作为起点。基本上,我需要更改紧接着 CID .BUS .DKV 行的 SizeisMeasured 行的第一次出现。但中间还有许多其他行(每个文件都不一致),我不关心这些行,而且这些行会弄乱我的搜索。
答案1
您可以像这样使用负向前瞻。搜索
(?!<CID>.*BUS..*.DKV</CID>(.*?))<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
并替换为
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
正则表达式,匹配.换行符
负向前瞻(?!a)
和负向后瞻(?<!a)
,也称为环视。环视匹配字符,但随后放弃匹配,仅返回结果:匹配或不匹配。
您可以在此处找到更多信息 前瞻和后瞻零长度断言
答案2
使用正则表达式解析 XML 并遵守层次结构会非常困难。我会使用完全不同的工具,该工具专为您要执行的操作而设计,即转换 XML。我说的是 XSLT。因此,这是我使用 XSLT 解决您问题的解决方案。有许多网站可用于使用 XSLT 转换 XML,或者您可以在本地运行 XSLT。
如果您的每个组(CID 后跟 SizeIsMeasuredLineLine)都在一个父级中,那么问题会变得简单,但下面的代码会查看第一个前面的 CID 兄弟,以查看它具有什么值。如果它具有与正则表达式 (ITEMNAME.[^.]+.ITEMNAME..+) 匹配的值,那么它会将 false 更改为 true。所有其他元素都只是复制到输出中。
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SizeIsMeasuredLineLine[matches(preceding-sibling::CID[1], 'ITEMNAME\.[^.]+\.ITEMNAME\..+')]">
<xsl:copy>TRUE</xsl:copy>
</xsl:template>
下面是我为测试上述内容而创建的示例 XML:
<?xml version="1.0" encoding="UTF-8"?>
<parent>
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.BUS.122.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.BUS.44.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.BUS.33.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
</parent>