【问题标题】:Partially Parsing XML File Without XMLParser in JAVA在 JAVA 中不使用 XMLParser 部分解析 XML 文件
【发布时间】:2011-06-29 17:34:26
【问题描述】:

所以我发现可以使用缓冲的读取器/写入器将 xml 文件逐字逐句地复制到新的 xml 文件中。但是,我想知道是否可以只刮掉文档的一部分?

例如看这个例子:

<?xml version="1.0" encoding="UTF-8"?>
<BookCatalogue xmlns="http://www.publishing.org">
    <w:pStyle w:val="TOAHeading" />
    <Book>
    <Title>Yogasana Vijnana: the Science of Yoga</Title>
    <author>Dhirendra Brahmachari</Author>
    <Date>1966</Date>
    <ISBN>81-40-34319-4</ISBN>
    <Publisher>Dhirendra Yoga Publications</Publisher>
    <Cost currency="INR">11.50</Cost>
  </Book>
  <Book>
    <Title>The First and Last Freedom</Title>
    <v:imagedata r:id="rId7" o:title="" croptop="10523f" cropbottom="11721f" /> 
    <Author>J. Krishnamurti</Author>
    <Date>1954</Date>
    <ISBN>0-06-064831-7</ISBN>
    <Publisher>Harper &amp; Row</Publisher>
    <Cost currency="USD">2.95</Cost>
  </Book>
<w:pStyle w:val="TOAHeading2" />
</BookCatalogue> 

对不起,如果这不是正确的 XML 代码,我只是将我正在查看的文档中的花絮添加到我找到的这个示例中。但基本上,如果我想查找“标题”的一个实例(在本例中为第 3 行 -> TOAHeading),则从标题向下抓取所有内容,直到找到另一个标题实例并将其复制到另一个 xml 文件。那可能吗?此外,如果我想将其作为我要存储的临时文件,并且仅在找到“图像”实例(在本例中为第 14 行)时才保留该文件,这也可能吗?我正在尝试以最简单的方式做到这一点,那么有人对此有任何想法或经验吗?提前致谢。

public class IPDriver 
        {
            public static void main(String[] args) throws IOException
            {
                BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStreamReader("C:/Documents and Settings/user/workspace/Intern Project/Proposals/Converted Proposals/Extracted Items/ProposalOne/word/document.xml"), "UTF-8"));
                BufferedWriter writer = new BufferedWriter(new OutputStreamReader(new FileOutputStreamReader("C:/Documents and Settings/user/workspace/Intern Project/Proposals/Converted Proposals/Extracted Items/ProposalOne/word/tempdocument.xml"), "UTF-8"));

                String line = null;

                while ((line = reader.readLine()) != null)
                {
                    writer.write(line);
                }

                // Close to unlock.
                reader.close();
                // Close to unlock and flush to disk.
                writer.close();
            }
        }

我的实际 XML 文档中的示例

- <w:smartTag w:uri="urn:schemas-microsoft-com:office:smarttags" w:element="address">
- <w:smartTag w:uri="urn:schemas-microsoft-com:office:smarttags" w:element="Street">
- <w:r w:rsidRPr="00822244">
  <w:t>6841 Benjamin Franklin Drive</w:t> 
  </w:r>
  </w:smartTag>
  </w:smartTag>
  </w:p>
- <w:p w:rsidR="00B41602" w:rsidRPr="00822244" w:rsidRDefault="00B41602" w:rsidP="007C3A42">
- <w:pPr>
  <w:pStyle w:val="Address" /> 
  </w:pPr>
- <w:smartTag w:uri="urn:schemas-microsoft-com:office:smarttags" w:element="City">
- <w:smartTag w:uri="urn:schemas-microsoft-com:office:smarttags" w:element="place">

只是来自 .docx 的基本 document.xml 文件

【问题讨论】:

  • @maasg 不。从事一个项目(工作),这只是较大项目的一部分,但我对使用 xml 相当陌生
  • 我个人会使用 xmlparser 库(例如 dom4j),但是如果你有这个要求,为什么不逐行扫描文件并检查每一行是否包含“标题”一词。如果是,则开始编写下一行,直到找到包含“标题”的另一行。同时,您还可以检查某行是否包含“”。一旦你来到第二个“标题”,你就会根据你的结果存储或删除临时文件。然而,这是一种幼稚的实现,正如我所说,出于多种原因,使用 xml 库会更好

标签: java xml parsing file-io xml-parsing


【解决方案1】:

您可能想阅读有关 java XML Parsers 的内容。有两种类型,SAX 解析器和 DOM 解析器。

SAX 解析器是“基于事件的”,这意味着解析器将为您扫描 xml 文件并调用您定义的一组“回调”方法,例如 startElement() 和 endElement()。 SAX 解析器对于非常大的 xml 文件非常有效。

DOM 解析器会将整个 XML 读入内存,然后您可以通过调用 getElementsByTagName("w:pStyle") 之类的方法来查询“DOM 对象”。 Dom 解析器往往更容易使用,但比 SAX 解析器使用更多内存。

会有一点学习曲线,但这些是在 java 中处理 XML 的标准方法。还有一些旨在简化标准库的库,例如 JDom。

【讨论】:

    【解决方案2】:

    我看到了很多技术上正确的建议,但您的请求(按书面形式)向我表明您有以下要求:

    • 属性值的不区分大小写(可能是部分)匹配开始解析;在您的情况下,您希望将“标题”与“TAOHeading”的后半部分匹配。
    • 从奇数开始条件向下解析到​​匹配(同样奇数)结束条件。

    如果我理解您的要求,那么您基本上是想要对非常结构化的数据(XML 标记)进行完全非结构化的解析。在这种情况下,使用 XML 解析器、XSLT 和 DOM 解析器来处理任何针对 XML 规范编写的内容都很难满足您的需求。

    您需要对文档内容进行不区分大小写的扫描,直到找到匹配项,然后提取该匹配项和结束匹配项之间的所有字符。

    如果文档不是很大(比如 1 MB 或更小),只需将整个内容读入内存中的字符串,然后对您想要的不同大小写版本使用非常快速而肮脏的“indexOf”,或者将整个内容读入 char[] 为您要开始解析的起始值编写一些更有效的扫描代码,以匹配不区分大小写的起始值。

    如果我误解了您的要求,并且它实际上比您在上面的描述中听起来更加结构化,那么请使用更专注于真正的 XML 解析的其他建议之一。我只是把这个解决方案放在那里,因为它就像你想象的那样随机。

    (注意:我并不是说这很糟糕,只是以前从未见过该请求。您有自己的理由需要这样做,我们会尽力提供帮助;)

    【讨论】:

      【解决方案3】:

      执行此操作的正确方法是使用XSLT 转换,该转换会发出除您不想要的所有内容之外的所有内容。这正是 XSLT 的意义所在。

      不要手动解析会导致失败,千万别想用正则表达式会导致史诗般的失败。

      如果您无法理解 XLST,并且它是从过程编码的范式转变,请在此处寻求帮助,或者在您的用例中使用传统的 XML 解析库,您可能不得不使用一些 @基于987654323@的解析器,我更喜欢JDOM

      【讨论】:

      • @Jarrod Roberson 我将研究 XSLT,但对于这个项目的其他部分,我使用 XML 解析我正在使用 SAX(主要是因为我正在使用的 xml 文档没有定义明确的树结构......因此我避免使用 DOM)。那么您认为 SAX 有一个可行的解决方案吗?
      • Does does not have a well-defined tree-structure 意味着它们的格式不正确(即开始和结束标签没有正确嵌套),或者存在没有类型定义或架构?
      • @Paŭlo Ebermann 表示前者(嵌套不正确)。我在原始帖子中包含了一些示例代码。
      • @This:它看起来嵌套很好(假设您发布的摘录之前有一个&lt;w:p&gt; 标签,最后两行中的两个标签稍后关闭)。 (它没有缩进,但 XML 不需要。) SAX 解析器也不应该接受格式不正确的 XML。 (如果某些东西格式不正确,那它就不是 XML,只是一种类似 XML 的语言。我认为 docx 是真正的 XML。)
      • @Paŭlo Ebermann 嗯,很有趣。我与之交谈的人(我认为他对这个主题非常了解)说结构对他们来说看起来很奇怪,所以这就是我的假设基础。然而,即使使用 DOM,它也只能向下读取,所以如果我想识别“图像”的一个实例并废弃它上面的所有内容......那是不可能的,对吗?
      【解决方案4】:

      如果您确定您的 XML 看起来像这样,您可以简单地将每一行与 &lt;w:pStyle w:val="TOAHeading" /&gt; 进行比较,然后开始输出以下行,直到找到与 &lt;w:pStyle w:val="TOAHeading2" /&gt; 匹配的行.

      但是你为什么要这样做呢?任何格式更改都很脆弱。 使用 XML 解析器(和 XML 编写器),让生活变得更轻松

      【讨论】:

      • 如果它被缩小并且没有换行符怎么办?有 XML 解析器是有原因的,使用它们。
      • 看看我考虑逐行阅读这篇文章(没有解析器)的原因是我可以识别标题和标题之间的图像实例,然后刮掉部分甚至刮掉找出标题和标题之间的部分到临时文件,确定图像实例是否存在,如果不存在则丢弃,否则......然后我将使用 SAX 解析器在新创建的文件中查找我正在寻找的属性XML 文档。这似乎是一个好方法,还是效率低下?因为据我所知,您无法使用 XML 解析器读取备份,对吧?
      • @Jarrod:是的,我也写了这个。也许我应该在我的回答中添加一些重点。
      • @This:这将是使用类似 DOM 的 API 而不是 SAX 的原因。看看詹姆斯的回答。
      • @Jarrod - 他的请求很奇怪(想要从不区分大小写的属性 VALUE 解析到另一个),为此使用 XML 解析器会很麻烦,因为他正在做的不是 XML 解析......这是一只奇怪的鸭子。
      猜你喜欢
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      • 2015-11-10
      • 2022-10-03
      • 1970-01-01
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多