开发者

Regex/Parse an XML file

I have an XML file with a bunch of data contained by custom tags. This is all useful for one project I have, but for another project I don't need so much info. So I'd like to trim the XML file, and get rid of all instances of certain tags and whatever is between the tags.

<GOBJ>
    <cost>4</cost>
    <duration>n/a</duration>
    <item>Stone Block</item>
    <type>Construction - Material</type>
    <misc>Use these blocks to build things. These blocks don't degrade.</misc>
</GOBJ>

I only want to keep [item]blah[item] and [type]blah[type], the rest开发者_运维知识库 should be deleted/removed.

Later on, I will need to check the text of [type] and replace its contents if it matches certain words. For example, if the word metal is anywhere within the [type] tag, then replace the contents of that tag with just the word metal.

I know this is a big request; I appreciate any help.


Another way is to just use simple XML → XML (XSLT 1.0 with XPath 1.0) transformation like below. It's easy to adapt for your requirements and reuse for other documents.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="root">
        <root>
            <xsl:apply-templates select="GOBJ"/>
        </root>
    </xsl:template>

    <xsl:template match="GOBJ">
        <GOBJ>
            <xsl:copy-of select="item"/>
            <type>
                <xsl:choose>
                    <xsl:when test="contains(type, 'metal')">
                        <xsl:text>metal</xsl:text>
                    </xsl:when>
                    <!-- other xsl:when conditions here -->
                    <xsl:otherwise>
                        <xsl:value-of select="type"/>
                    </xsl:otherwise>
                </xsl:choose>
            </type>
        </GOBJ>
    </xsl:template>
</xsl:stylesheet>

I know it's not regex based solution, but IMHO it's better to use native XML-oriented toolkit.


Assuming that the file is laid out exactly as your example, multiplied by as many records as required, and that you wish to preserve the original layout as much as possible, replacing

(<GOBJ>[^<]+?).+?(<item>.+?<\/type>\n).+?(<\/GOBJ>)

with

$1$2$3

globally and the regex is set to operate in 'singleline' mode, will do what you require iff, element <GOBJ> is uppercase, other elements are in lowercase, there is ever only one instance of each element per record, and element <item> always appears immediately before element <type> in each record.

In JavaScript, this would be:

var result = src.replace(
    /(<GOBJ>[^<]+?).+?(<item>.+?<\/type>\n).+?(<\/GOBJ>)/g, 
    '$1$2$3'
);

Note that the strict conditions alleviate any issues related to parsing XML using a regular expression. If the conditions cannot be met, you would be far better served using an XML-specific tool, like XSLT.


Here's a grep solution: grep -E '(<item>|<type>)' myfile.xml


I developed another way to tackle the problem; I built a jquery script that split up the xml code (i replaced all the left/right arrows with a different symbol before hand), and output the array entry if i didn't contain another certain symbol.

var name = $('div').text().trim().split(/\[name\](.*?)\[\/name\]/g);
var type = $('div').text().trim().split(/\[type\](.*?)\[\/type\]/g);
for (i = 0; name.length > i; i++) {
        if ((type[i].match(/\[/g))) {
            type[i] = "";
        }
        if (!(name[i].match(/\[/g))) {
            if (type[i].match(/construction/g)) {type[i] = "T_C";}
            if (type[i].match(/material/g)) {type[i] = "T_M";}
            if (type[i].match(/metalwork/g)) {type[i] = "T_W";}
            if (type[i].match(/water/g)) {type[i] = "T_W";}
            if (type[i].match(/oil/g)) {type[i] = "T_O";}
            if (type[i].match(/precious/g)) {type[i] = "T_P";}
            if (type[i].match(/magic/g)) {type[i] = "T_M";}
            $('.Collect').append('<p>a href="../Img/XXX/' + name[i] + '.jpg" class="' + type[i] + '">' + name[i] + '/a></p>');
        } else {
            name[i] = "";
        }

    }

The output is formatted that way so that i can just copy paste the page into a txt/html file, and have it pretty much as i wanted it. I'll have to figure out some way to replace XXX with the appropriate Directory name...

I only needed to do this once or twice, so pure automation wasn't imperative.


If you want to parse XML log file so you can do with regex {java}, <[^<]+<.so you get <name>DEV</name>. Output like name>DEV.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜