1

I have a tricky problem. I need to make a minor change to a large number of xml files (500+). The change involves switching a value from 'false' to 'true.' The line that needs to change looks like this:

<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>

And it needs to become:

<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>

Unfortunately there are numerous instances of this set of tags in each file, so we can't do a simple find and replace. The thing that makes this set of tags unique is that they come some lines after:

<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>

However, each file has a different item name, so I had used wildcards to filter them out.

<CID>.*BUS..*.DKV</CID>

The problem is, the number of lines in between the CID part and the line that needs to change is not consistent from file to file. I need to find a way to wildcard out the lines in between, and replace the Size line.

Any ideas? I have already tried:

<CID>.*BUS..*.DKV</CID>.*?<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>

But for some reason that did not work. Thank you in advance!

Edit in Response to Comment:

Basically what I'm saying is the code looks like this:

<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>

And other sections in the code look like:

<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>

in other places in the code. So I'm using the CID .BUS .DKV line as a starting point. Basically I need to change the first occurance of the SizeisMeasured line that comes directly AFTER the CID .BUS .DKV line. But there's a lot of other lines in between (none of which are consistent from file to file) that I don't care about and are messing up my search.

1
  • post one (or two) example of your code in pastecode.org and give a link in your question. This will give us a better idea
    – Prasanna
    Apr 15, 2015 at 18:21

2 Answers 2

1

You can use negative lookahead like this. Search

(?!<CID>.*BUS..*.DKV</CID>(.*?))<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>

and replace with

<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>

Regular Expression , matching . newline

Negative Lookahead (?!a) and Negative Lookbehind (?<!a), Are also refered too as Lookaround. Lookaround matches characters, but then gives up the match, returning only the result: match or no match.

You can find more here Lookahead and Lookbehind Zero-Length Assertions

1
  • Thank you, but that search also finds other CID tags that I don't want, like: <CID>ITEMNAME.COLR.L1201.FCLR</CID> The .BUS and .DKV portions are very important to distinguish the line/section I need. How do I modify the search so it doesn't ignore those parts? Apr 16, 2015 at 12:01
0

Parsing XML while honoring the heirarchy with Regular Expressions is unnecessarily difficult. I would use a completely different tool that is explicitly designed for what you are trying to do, which is transform XML. I'm talking about XSLT. So, here is my solution for your problem using XSLT. There are a number of web sites out there that you could use to convert your XML with XSLT, or you could run XSLT locally.

The problem would be easier if each of your groups (CID followed by SizeIsMeasuredLineLine) were within a single parent, but the code below looks at the first preceeding CID sibling to see what value it has. If it has a value matching the regular expression (ITEMNAME.[^.]+.ITEMNAME..+) then it changes the false to true. All other elements are simply copied to the output.

<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>

Here is the sample XML that I created to test the above:

    <?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>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.