【问题标题】:Best way transform custom XML like syntax转换自定义 XML 类语法的最佳方式
【发布时间】:2011-10-06 09:17:50
【问题描述】:

使用 Python。

所以基本上我有一个类似 XML 的标签语法,但标签没有属性。所以<a> 但不是<a value='t'>。他们定期关闭</a>

这是我的问题。我有一些看起来像这样的东西:

<al>
1. test
2. test2
 test with new line
3.  test3
<al>
    1. test 4
    <al>
        2. test 5
        3. test 6
        4. test 7
    </al>
</al>
4. test 8
</al>

我想把它变成:

<al>
<li>test</li>
<li> test2</li>
<li> test with new line</li>
<li>  test3
<al>
    <li> test 4 </li>
    <al>
        <li> test 5</li>
        <li> test 6</li>
        <li> test 7</li>
    </al>
    </li>
</al>
</li>
<li> test 8</li>
</al>

我并不是真的在寻找一个完整的解决方案,而是朝着正确的方向前进。我只是想知道这里的人们将如何解决这个问题。唯一的正则表达式?为无属性标记语法编写一个完整的自定义解析器?破解现有的 XML 解析器?等等

提前致谢

【问题讨论】:

  • 这是一次性任务还是需要再次完成?您是否必须 100% 正确转换它,还是可以手动更正?
  • 文件中出现的次数。我想让间距尽可能接近 100% 正确。
  • @mac 抱歉,这是一个错字,这种转换仅适用于 在这种情况下。虽然会有其他类似的标签。
  • @peach - 然后删除了我的 cmets。当发现拼写错误时,您应该修复您的问题! :o 这次我是为你做的 ;)
  • 既然提到了 XML 和正则表达式,我必须链接我最喜欢的 SO 答案:stackoverflow.com/questions/1732348/…

标签: python xml parsing tags


【解决方案1】:

您描述语法的方式是“没有属性的 XML”。如果是这样,它仍然是 XML,因此您可以使用 XML 工具,例如 XSLT 和 XQuery。

另一方面,如果您允许 XML 中不允许的内容,我的方法是编写一个解析器来处理您的非 XML 格式并提供与 XML 兼容的 SAX 事件。然后,只需插入解析器代替常规 XML 解析器,您就可以使用任何 XML 技术。

【讨论】:

    【解决方案2】:

    这将取决于你想用它做什么,如果它是一个脚本,以下就足够了:

    cat in.txt | perl -pe 'if(!/<\/?al>/){s#^(\s*)([0-9]+\.)?(.*)$#$1<li>$3</li>#}'
    

    而且它有效。但我不会说它非常强大;)但如果它是一次性的,那很好。

    【讨论】:

      【解决方案3】:

      我只是想知道这里的人会如何解决这个问题。

      我会选择使用解析器。

      我的理由是,您尝试执行的操作不仅仅是句法或词法替换。这更像是一种语法转换,这意味着了解文档的结构

      在您的示例中,您不只是将每一行括在 &lt;li&gt;&lt;/li&gt; 之间;如果它们代表一个“项目”,您还将递归地包含一些跨越多行的文档块。

      也许您可以组合一个能够捕捉问题的解释性逻辑和递归性质的正则表达式,但这样做就像用茶匙挖沟:您可以 这样做,但使用铲子(解析器)是更合乎逻辑的选择。

      使用解析器的另一个原因是“真实单词”。正则表达式是真正的“语法纳粹”:您的标记出现故障,它们将无法正常工作。另一方面,所有解析器库都是“灵活的”(统一处理不同的拼写,如&lt;a&gt;&lt;/a&gt;&lt;a/&gt; 或HTML 的&lt;br&gt; 和XHTML 的&lt;br/&gt;),有些——比如beautifulsoup——甚至是“宽容的”,这意味着他们会尝试(以惊人的高准确度)猜测文档作者想要编码的内容,即使文档本身未通过验证。

      此外,基于解析器的解决方案比基于正则表达式的解决方案更易于维护。您的文档结构中的一个小改动可能需要对您的正则表达式进行彻底的更改(在 72 小时左右后,它们的作者自然会变得晦涩难懂)。

      最后,由于您使用的是 python 和 therefore readability counts,因此基于解析器的解决方案可能会产生比非常复杂/长/晦涩的正则表达式更多的 Python 代码。

      HTH!

      【讨论】:

      • 感谢 mac,我想我会做一个简单的基于正则表达式的标记器并从那里解析它。
      【解决方案4】:

      我建议从以下开始:

      from xml.dom.minidom import parse, parseString
      
      xml = parse(...)
      l = xml.getElementsByTagName('al')
      

      然后遍历l 中的所有元素,检查它们的文本子节点(以及递归地检查&lt;al&gt; 节点)。

      您可以立即在 Python 控制台中开始使用它。

      删除文本节点很容易,然后根据需要使用chunk.split('\n') 拆分文本块并添加&lt;li&gt; 节点。

      修改完所有&lt;al&gt; 节点后,您只需调用xml.toxml() 即可将生成的xml 作为文本获取。

      请注意,您从中获得的元素对象会链接回原始的xml 文档对象,因此请不要在此过程中删除xml 对象。

      我个人认为这种方式比使用多行正则表达式更直接且易于调试。

      【讨论】:

        猜你喜欢
        • 2012-04-18
        • 1970-01-01
        • 1970-01-01
        • 2012-01-10
        • 2011-05-12
        • 2015-03-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多