0

I am not sure how to use regex to do the following: within the edge tags (), check if type="highway.secondary", and if yes, replace all values of speed to 40.

<edge id="-100396051#2" type="highway.unclassified">
        <lane id="-100396051#2_0" index="0"  speed="13.89">
            <param key="origId" value="100396051"/>
        </lane>
    </edge>
    <edge id="-101784374#0" type="highway.secondary">
        <lane id="-101784374#0_0" index="0"  speed="27.78" length="17.22" >
            <param key="origId" value="101784374"/>
        </lane>
        <lane id="-101784374#0_1" index="1" speed="29.98" length="17.22" >
            <param key="origId" value="101784374"/>
        </lane>
    </edge>

So far I got this: (?<=type="highway\.secondary")(speed)(?=edge), but that doesn't find speed... Thanks!

Puki Luki
  • 573
  • 1
  • 4
  • 13
  • 7
    Use an XML parser instead – CertainPerformance Apr 02 '19 at 06:38
  • 1
    My answer should solve your problem! It is based on XSLT technologies to parse the input XML and generate the desired XML output – Allan Apr 02 '19 at 09:28
  • 1
    Some call it [summoning the daemon](https://www.metafilter.com/86689/), others refer to it as [the Call for Cthulhu](https://blog.codinghorror.com/parsing-html-the-cthulhu-way/) and few just [turned mad and met the Pony](https://stackoverflow.com/a/1732454/8344060). In short, never parse XML or HTML with a regex! Did you try an XML parser such as `xmlstarlet`, `xmllint` or `xsltproc`? – kvantour Apr 04 '19 at 08:59

1 Answers1

2

INPUT: edges.xml

<edges>
  <edge id="-100396051#2" type="highway.unclassified">
        <lane id="-100396051#2_0" index="0"  speed="13.89">
            <param key="origId" value="100396051"/>
        </lane>
    </edge>
    <edge id="-101784374#0" type="highway.secondary">
        <lane id="-101784374#0_0" index="0"  speed="27.78" length="17.22" >
            <param key="origId" value="101784374"/>
        </lane>
        <lane id="-101784374#0_1" index="1" speed="29.98" length="17.22" >
            <param key="origId" value="101784374"/>
        </lane>
    </edge>
</edges>

STYLESHEET: change_speed.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" encoding="utf-8" indent="yes"/>

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

<xsl:template match="@speed[../parent::edge and ../../@type='highway.secondary']">
    <xsl:attribute name="speed">
      <xsl:value-of select="'40'"/>
    </xsl:attribute>
</xsl:template>


</xsl:stylesheet>

OUTPUT:

$ xsltproc change_speed.xsl edges.xml 
<?xml version="1.0" encoding="utf-8"?>
<edges>
  <edge id="-100396051#2" type="highway.unclassified">
        <lane id="-100396051#2_0" index="0" speed="13.89">
            <param key="origId" value="100396051"/>
        </lane>
    </edge>
    <edge id="-101784374#0" type="highway.secondary">
        <lane id="-101784374#0_0" index="0" speed="40" length="17.22">
            <param key="origId" value="101784374"/>
        </lane>
        <lane id="-101784374#0_1" index="1" speed="40" length="17.22">
            <param key="origId" value="101784374"/>
        </lane>
    </edge>
</edges>

Explanations:

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

Will copy all the nodes and attributes recursively

<xsl:template match="@speed[../parent::edge and ../../@type='highway.secondary']">
    <xsl:attribute name="speed">
      <xsl:value-of select="'40'"/>
    </xsl:attribute>
</xsl:template>

When you reach an attribute named speed for which the parent node is named edge and has an attribute type whose value is at highway.secondary, change the value of this attribute to 40.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
Allan
  • 12,117
  • 3
  • 27
  • 51