【问题标题】:Converting XML input from multiple lines to one line将 XML 输入从多行转换为一行
【发布时间】:2010-12-04 03:46:10
【问题描述】:

我有一个这样的xml

<address>
   <street>abc</street>
   <number>123</number>
</address>

<address>
   <street>abc1</street>
   <number>345</number>
</address>

...
...
<address>
   <street>xyz</street>
   <number>999</number>
</address>

我希望能够将其转换为

<address><street>abc</street><number>123</number></address>
<address><street>abc1</street><number>345</number></address>
...
...
<address><street>xyz</street><number>999</number></address>

您能否推荐我如何解决这个问题,我认为 sed 可能会有所帮助,但无法使其正常工作。

编辑:XML 文件有 100K 行类似类型,经过编辑以反映正确的输入和输出。

【问题讨论】:

  • 我有大约 100K 行,我将编辑问题以反映这一点

标签: java xml perl sed


【解决方案1】:

[XML::Twig][1] 带有一个漂亮的 xml 打印机 xml_pp。如果地址行就在文档的根目录下,那么您可以使用它来真正接近您想要的输出:

xml_pp -s record_c to_compact.xml

<root>
  <address><street>abc</street><number>123</number></address>
  <address><street>abc1</street><number>345</number></address>
  <address><street>xyz</street><number>999</number></address>
  <address><street>abc</street><number>123</number></address>
  <address><street>abc1</street><number>345</number></address>
  <address><street>xyz</street><number>999</number></address>
</root>

删除地址行开头的空格很容易:

xml_pp -s record_c to_compact.xml | perl -p -e's{^\s+}{}'

如果地址元素不在根目录下,请告诉我们,我会看看能做些什么。

【讨论】:

    【解决方案2】:

    我不确定它的命令行语法,但是这个正则表达式应该可以做到:

    // Find:
    />[\n\s]+</
    // Replace with:
    ><
    

    这只会去除元素之间的空格(不在元素内部,除非它可能是 CDATA 部分),但您可能会不小心删除一些您真正想要的空格,例如:

    <p>here's <i>something</i> <b>interesting</b></p>
    // becomes:
    <p>here's <i>something</i><b>interesting</b></p>
    

    这是我提到的 CDATA 问题的一个示例:

    <element><![CDATA[
        this shouldn't <blah>
        <blah> be touched.
    ]]></element>
    
    // becomes:
    <element><![CDATA[
        this shouldn't <blah><blah> be touched.
    ]]></element>
    

    当然,“正确”的答案是使用解析器读取文件,然后再次输出,去掉空格和缩进。

    【讨论】:

      【解决方案3】:

      另一种选择是使用 XSLT 样式表,它复制所有内容,但只复制地址元素中的元素和属性:

      <?xml version="1.0"?>
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:template match="@*|node()">
              <xsl:copy>
                  <xsl:apply-templates select="@*|node()"/>
              </xsl:copy>
          </xsl:template>
      
          <xsl:template match="address">
              <xsl:copy>
                  <xsl:apply-templates select="@*|*"/>
              </xsl:copy>
          </xsl:template>
      </xsl:stylesheet>
      

      与正则表达式方法不同,这应该适用于任何 XML 文档(即使换行符被编码为字符实体或在 CDATA 中),并且只会格式化地址元素。

      您可以使用 Java 运行样式表,也可以使用 xsltproc 从命令行运行。

      【讨论】:

        【解决方案4】:

        您可以编写一个 SAX 解析器,并且在每个事件上只需将元素写入另一个文件而无需换行。这将删除新行和垃圾空格。

        【讨论】:

          【解决方案5】:

          你可以试试这个代码(Java):

          import java.util.Scanner;
          import java.io.File;
          import java.io.FileWriter;
          public class TrimLines {
            public static void main(String[] args){
              try {
                  String source = "employee.xml";
                  String result = "no-lines-employee.xml";
          
                  System.out.println("removing lines...");
                  Scanner s = new Scanner(new File(source));          
                  FileWriter w = new FileWriter(result);          
                  while(s.hasNext())              
                      w.write(s.nextLine());          
                  w.close();          
                  System.out.println("remove successfull.");
              }
              catch(Exception ex){
                  ex.printStackTrace();
              }
            } 
          }
          

          只需指定源 xml 文件名(源变量)和目标 xml 文件名(结果变量)。

          【讨论】:

          • 您也可以在 s.nextLine() 之后添加 trim() 以删除标签之间的空白。
          【解决方案6】:

          试试这个选项: 在记事本++ > 打开 xml 文件 > 选择所有内容并在编辑中选择 > 空白操作 > 删除不必要的空白和 EOL。

          这对我有用。

          【讨论】:

            【解决方案7】:

            此链接应该对您有所帮助。他们的例子有点复杂,但应该不难改变以满足您的需求: http://www.unix.com/unix-dummies-questions-answers/40871-remove-carriage-return-between-line.html

            -不要

            【讨论】:

              【解决方案8】:

              tr 是一种非常简单的替换换行符的方法:

              cat addresses.xml | tr -d '\n'
              

              谷歌搜索“shell replace newline”也会产生很多其他选项。

              【讨论】:

                【解决方案9】:

                正则表达式

                (?<=>)\r?\n[ \t]*(?!<address)
                

                将匹配标签之间的 CRLF + 空格/标签,除非后面跟着 &lt;address&gt;。虽然我通常建议不要使用正则表达式和解析器,但在这种情况下,看起来这样可以更轻松地完成工作。

                【讨论】:

                • 投反对票的人能解释一下投票吗?该解决方案适用于示例数据,并且还存在关于正则表达式与解析器的警告。
                猜你喜欢
                • 1970-01-01
                • 2018-04-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多