如何从XML字符串中删除XML意向? 一些背景解决方案的方法

问题描述

我有一个XML字符串。我无法从XML字符串中删除缩进空间。我替换了换行符。

  <person id="13">
      <name>
          <first>John</first>
          <last>Doe</last>
      </name>
      <age>42</age>
      <Married>false</Married>
      <City>Hanga Roa</City>
      <State>Easter Island</State>
      <!-- Need more details. -->
  </person>

如何从GOLANG中的字符串中删除XML缩进空间?

我希望这个XML像字符串一样,

<person id="13"><name><first>John</first><last>Doe</last></name><age>42</age><Married>false</Married><City>Hanga Roa</City><State>Easter Island</State><!-- Need more details. --></person>

如何在GOLANG中做到这一点?

解决方法

一些背景

不幸的是,XML不是regular language,因此,您将无法使用正则表达式可靠地对其进行处理-无论您将要使用的正则表达式多么复杂。

我将从this幽默幽默的话题开始,然后读this

例如,对示例进行的简单更改可能会破坏您的处理,例如:

  <person id="13">
      <name>
          <first>John</first>
          <last>Doe</last>
      </name>
      <age>42</age>
      <Married>false</Married>
      <City><![CDATA[Hanga <<Roa>>]]></City>
      <State>Easter Island</State>
      <!-- Need more details. -->
  </person>

实际上,考虑一下

<last>Von
Neumann</last>

您为什么认为可以自由地从该元素的内容中删除换行符?

您肯定会说,他们的姓氏中没有明显的换行符。
好吧,那呢?

<poem author="Chauser">
  <strophe number="1">  The lyf so short,the craft so long to lerne.</strophe>
</poem>

您不能明智地将句子的两部分之间的空格删除-因为它是作者的意图。

好吧,完整的故事在the section called "White Space Handling" of the XML spec中定义。
外行尝试用XML描述空格处理的尝试如下:

  • XML规范本身没有为空格赋予任何特殊含义:决定XML文档的特定位置中的空白是什么该文档的处理者。

    通过扩展,该规范没有规定任何“标签”(<foo></bar><quux/>事物之间的空白)是否出现在是否重要:只有您来决定。
    为了更好地了解其原因,请考虑以下文档:

    <p>␣Some text which contains an␣<em>emphasized block</em>
    which is followed by a linebreak and more text.</p>
    

    这是一个非常有效的XML,我已经替换了空格字符 在<p>标记之后和<em>标记之前,以及带有Unicode“打开框”字符的第二个字符。

    请注意,整个文本␣Some text which contains an␣出现在两个标签之间,并且包含前导空格和尾随空格,显然是重要;如果不是,则强调文本(标有{ {1}}将与前面的文本粘合在一起。

    相同的逻辑适用于换行符和<em>…</em>标记之后的更多文本。

  • XML规范提示,定义“无关紧要”的空白可能很方便,以表示一对未定义单个元素的相邻标记之间的任何空白。

XML还有两个特征,这些特征使处理进一步复杂化:

  • 字符实体(那些</em>&amp;东西)允许直接插入任何Unicode代码点:例如,&lt;将插入换行符。
  • XML支持特殊的"CDATA sections",您的解析器表面上对此一无所知。

解决方案的方法

在尝试提出解决方案之前,我们先定义要忽略的空白,然后丢弃。

类似于您的文档,其定义应为:除非两个条件,否则删除任何两个标签之间的任何字符数据:

  • 它至少包含一个单一的非空白字符,或者
  • 它完全定义了单个XML元素的内容。

考虑到这些注意事项,我们可以编写将输入XML流解析为 tokens 并将其写入输出XML流中的代码,同时将以下逻辑应用于处理令牌:

  1. 如果看到除字符数据之外的任何XML元素,则将它们编码为输出流。

    此外,如果该元素是开始标签,它会通过设置一些标志来记住这一事实;否则将清除该标志。

  2. 如果看到任何字符数据,它将检查该字符数据是否紧跟在起始元素(开始标记)之后,如果是,则将该字符数据块保存起来。

    当已经存在已保存的字符数据块时,也将保存字符数据块,这是必需的,因为在XML中,文档中可能有多个相邻但仍然不同的字符数据块。

  3. 如果看到任何XML元素,并且检测到它具有一个或多个保存的字符块,则它首先决定是否将其放入输出流:

    • 如果元素是结束元素(结束标记),则所有字符数据块都必须“按原样”放入输出流中,因为它们完全定义了单个元素的内容。

    • 否则,如果至少一个已保存的字符数据块包含至少一个非空白字符,则所有块均按原样写入输出流。

    • 否则将跳过所有块。

以下是实现上述方法的工作代码:

&#x000d;

Playground

我不确定它能否完全涵盖所有可能的怪异案例,但这应该是一个好的开始。

,

尤里卡

首先需要从XML删除缩进,然后需要删除换行符。

// Regex to remove indentation
m1 := regexp.MustCompile(`( *)<`)
newstr := m1.ReplaceAllString(xmlString,"<")

// Replace newline
newLineReplacer := strings.NewReplacer("\n","","\r\n","")
xmlString = newLineReplacer.Replace(newstr)

在这里https://play.golang.org/p/Orp2RyPbGP2

,

您可以简单地删除new linetab字符,如下所示:

package main

import (
    "fmt"
    "strings"
)

func main() {
    var s = `<person id="13">
    <name>
        <first>John</first>
        <last>Doe</last>
    </name>
    <age>42</age>
    <Married>false</Married>
    <City>Hanga Roa</City>
    <State>Easter Island</State>
    <!-- Need more details. -->
</person>`
    for {
        if strings.Contains(s,"\n") {
            s = strings.ReplaceAll(s,"\n","")
        }
        if strings.Contains(s,"\t") {
            s = strings.ReplaceAll(s,"\t","")
        }
        if !strings.Contains(s,"\n") && !strings.Contains(s,"\t") {
            break
        }
    }
    fmt.Println(s)
}

结果:

<person id="13"><name><first>John</first><last>Doe</last></name><age>42</age><Married>false</Married><City>Hanga Roa</City><State>Easter Island</State><!-- Need more details. --></person>
,

删除XML标签之间的仅空白序列

func unformatXML(xmlString string) string {
    var unformatXMLRegEx = regexp.MustCompile(`>\s+<`)
    unformatBetweenTags := unformatXMLRegEx.ReplaceAllString(xmlString,"><") // remove whitespace between XML tags
    return strings.TrimSpace(unformatBetweenTags) // remove whitespace before and after XML
}

RegEx说明

\ s -匹配任何空格,包括制表符,换行符,换页符,回车符和空格

+ -匹配一个或多个空格字符

RegEx语法参考:https://golang.org/pkg/regexp/syntax/

示例

package main

import (
    "fmt"
    "regexp"
    "strings"
)

func main() {
    var s = `    
<person id="13">
    <name>
        <first>John</first>
        <last>Doe</last>
    </name>
    <age>42</age>
    <Married>false</Married>
    <City>Hanga Roa</City>
    <State>Easter Island</State>
    <!-- Need more details. -->
</person>   `

    s = unformatXML(s)
    fmt.Println(fmt.Sprintf("'%s'",s)) // single quotes used to confirm no leading or trailing whitespace
}

func unformatXML(xmlString string) string {
    var unformatXMLRegEx = regexp.MustCompile(`>\s+<`)
    unformatBetweenTags := unformatXMLRegEx.ReplaceAllString(xmlString,"><") // remove whitespace between XML tags
    return strings.TrimSpace(unformatBetweenTags) // remove whitespace before and after XML
}

Go Playground中的可运行示例

https://play.golang.org/p/VS1LRNevicz

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...