1

我不确定这是否是一个简单的问题,但到目前为止我一直无法找到答案。我正在尝试编写一个正则表达式来拆分 .docx 文件并匹配用标签替换所有<w:tab />标签<w:ind />,因为<w:tab>标签在转换为 html 时似乎无法正确保留标签。我在 PHP 中工作,到目前为止,我一直未能成功编写一个正则表达式来完成我需要它正确执行的操作。

问题是,我不能在这里只运行一个简单的查找和替换功能。我必须删除<w:tab />标签并将标签注入<w:ind />最近的开始和结束<w:rPr></w:rPr>标签中。

示例 XML 字符串如下所示:

    <w:p w14:paraId="2679030C" w14:textId="4E6FFA99" w:rsidR="00ED4314" w:rsidRPr="00254747" w:rsidRDefault="00ED4314" w:rsidP="00322270">
        <w:pPr>
            <w:pStyle w:val="NoSpacing" />
            <w:spacing w:line="480" w:lineRule="auto" />
            <w:jc w:val="both" />
            <w:rPr>
                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman" />
                <w:sz w:val="24" />
                <w:szCs w:val="24" />
            </w:rPr>
        </w:pPr>
        <w:r w:rsidRPr="00254747">
            <w:rPr>
                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman" />
                <w:sz w:val="24" />
                <w:szCs w:val="24" />
            </w:rPr>
            <w:tab />
            <w:t>SOME text</w:t>
        </w:r>
        <w:r w:rsidR="0003297C">
            <w:rPr>
                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman" />
                <w:sz w:val="24" />
                <w:szCs w:val="24" />
            </w:rPr>
            <w:t>SOME more text</w:t>
        </w:r>
        <w:r w:rsidRPr="00254747">
            <w:rPr>
                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman" />
                <w:sz w:val="24" />
                <w:szCs w:val="24" />
            </w:rPr>
            <w:t>EVEN more text</w:t>
        </w:r>
    </w:p>

所以每个实例<w:tab/>都需要被删除,然后我需要回溯到前一个<w:rPr>标签并在其中注入一个<w:ind />标签。

继承人我到目前为止:

$content = preg_replace("/<w:rPr>(.*?)<\/w:rPr>(.*?)<w:tab\/>/", "<w:rPr><w:ind w:firstLine=\"720\"/>$1</w:rPr>$2", $content);

这种工作,但问题是我认为搜索过于全球化。即使我指定它不要贪婪,它返回给我的结果也比他们应该有的内容要多得多。任何人都可以提出一种优化的方法来完善这个吗?提前致谢!

4

1 回答 1

1

我认为您将非贪婪与正则表达式“知道”在找到更多标签之前停止 - 它不能。如果您的意思是禁止 and 之间的标签</w:rPr><w:tab/>那么这应该大致有效:

/<w:rPr>(.*?)<\/w:rPr>([^<]*?)<w:tab\/>/
                       ^^^^

这被称为否定字符类,并匹配所有不是的 <字符——因此在找到<w:tab/>.


编辑。作为对您的澄清的回应,除了 <w:rPr>在找到之前允许所有标签a <w:tab/>,您需要使用否定的前瞻断言,因为,正如您正确理解的那样,否定字符类仅排除字符,而不是字符串。

/<w:rPr>(.*?)<\/w:rPr>((?:(?!<w:rPr>).)*?)<w:tab\/>/
                       ^^^^^^^^^^^^^^^^

忽略(?:xyz)令人困惑的 if ——这只是一种让括号被捕获的方法——我需要括号来表示量词, *。这里重要的部分(?!xyz)是被称为负前瞻断言(顺便说一下也是一个非捕获组) -如果它向前看并且没有找到“xyz”,它匹配- 所以,我们在上面做的是这个: (1) 向前看,(2) 如果不是,则 (3) 匹配一个字符,和 (4) 重复——直到找到 a。 <w:rPr>.<w:tab/>

于 2013-11-05T05:58:12.347 回答