【问题标题】:Remove empty elements xml string java?删除空元素xml字符串java?
【发布时间】:2016-09-30 10:22:08
【问题描述】:

我有一个 xml 字符串,我想从中删除空元素和包含该元素的行。

举个例子:

XML:

<ct>
   <c>http://192.168.105.213</c>
   <l>http://192.168.105.213</l>
   <o></o>
   <l>http://192.168.105.213</l>
   <o>http://192.168.105.213</o>
<ct>

在这个&lt;o&gt;&lt;/o&gt; 是空元素,所以删除这个元素后我想要:

   <ct>
       <c>http://192.168.105.213</c>
       <l>http://192.168.105.213</l>
       <l>http://192.168.105.213</l>
       <o>http://192.168.105.213</o>
    <ct>

因此必须删除整行,使其缩进。

我试过了:xml.replaceAll("&lt;(\\w+)&gt;&lt;/\\1&gt;", ""));

这会在两者之间留下一个空行:

<ct>
   <c>http://192.168.105.213</c>
   <l>http://192.168.105.213</l>

   <l>http://192.168.105.213</l>
   <o>http://192.168.105.213</o>
</ct>

如何正确删除空格或\n, \t, \r 以获得正确的缩进?

【问题讨论】:

标签: java regex xml


【解决方案1】:

这可行:

xml.replaceAll("<(\\w+)></\\1>\n\\s+", ""));

它将匹配一个新行,后跟一个或多个空格(包括制表符),前面是您的模式。

编辑:xml.replaceAll("\n\\s+&lt;(\\w+)&gt;&lt;/\\1&gt;", "") 也应该适用于更深层次。

如果您希望根元素也为空并且任何子元素都是非预期的,则可能需要将换行符和空格设置为可选

xml.replaceAll("\n?\\s*<(\\w+)></\\1>", "")

【讨论】:

  • 它适用于一级缩进,但对于深度嵌套的空元素,这会删除适当的空格以保持缩进吗?
  • @SiddharthTrikha 请在标签前添加换行符+空格组合,就像编辑中一样。它应该适用于更深层次的人。
【解决方案2】:

这个应该可以帮你解决

xml.replaceAll("\n\t<(\\w+)></\\1>", "");

【讨论】:

    【解决方案3】:

    根据 cmets 的建议,重新考虑直接在 HTML/XML 文档上使用正则表达式,因为这些不是常规语言。相反,在解析的文本/值内容上使用正则表达式,而不是转换文档。

    XSLT 是一个很棒的 XML 操纵器工具,它是 XPath 的转换语言和兄弟。 Java 附带一个内置的 XSLT 1.0 处理器,并且还可以调用或获取外部处理器 (Xalan, Saxon, etc.)。考虑以下设置:

    XSLT 脚本(保存为下面使用的 .xsl 文件;脚本删除空节点)

    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output version="1.0" encoding="UTF-8" indent="yes" />
    <xsl:strip-space elements="*"/>
    
      <!-- Identity Transform to Copy Document as is -->
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <!-- Empty Template to Remove Such Nodes -->
      <xsl:template match="*[.='']"/>
    
    </xsl:transform>
    

    Java代码

    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    import javax.xml.transform.*;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.TransformerException;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    import javax.xml.transform.stream.StreamSource;
    import javax.xml.transform.OutputKeys;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.URISyntaxException;
    
    import org.w3c.dom.Document;
    import org.xml.sax.SAXException;
    
    public class XMLTransform {
        public static void main(String[] args) throws IOException, URISyntaxException,
                                                      SAXException, ParserConfigurationException,
                                                      TransformerException {            
                // Load XML and XSL Document
                String inputXML = "path/to/Input.xml";
                String xslFile = "path/to/XSLT/Script.xsl";
                String outputXML = "path/to/Output.xml";
    
                Source xslt = new StreamSource(new File(xslFile));            
                DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();            
                DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
                Document doc = docBuilder.parse (new File(inputXML));
    
                // XSLT Transformation  with pretty print
                TransformerFactory prettyPrint = TransformerFactory.newInstance();
                Transformer transformer = prettyPrint.newTransformer(xslt);
    
                transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
                transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
                transformer.setOutputProperty(OutputKeys.METHOD, "xml");
                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
                transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");                        
    
                DOMSource source = new DOMSource(doc);
                StreamResult result = new StreamResult(new File(outputXML));        
                transformer.transform(source, result);
        }
    }
    

    输出

    <ct>
        <c>http://192.168.105.213</c>
        <l>http://192.168.105.213</l>
        <l>http://192.168.105.213</l>
        <o>http://192.168.105.213</o>
    </ct>
    

    命名空间

    使用命名空间时,例如以下 XML:

    <prefix:ct xmlns:prefix="http://www.example.com">
       <c>http://192.168.105.213</c>
       <l>http://192.168.105.213</l>
       <o></o>
       <l>http://192.168.105.213</l>
       <o>http://192.168.105.213</o>
    </prefix:ct>
    

    使用以下 XSLT,在标题中声明并添加模板:

    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                   xmlns:prefix="http://www.example.com">
    <xsl:output version="1.0" encoding="UTF-8" indent="yes" />
    <xsl:strip-space elements="*"/>
    
      <!-- Identity Transform -->
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <!-- Retain Namespace Prefix -->
      <xsl:template match="ct">
        <xsl:element name='prefix:{local-name()}' namespace='http://www.example.com'>
          <xsl:copy-of select="namespace::*"/>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
      </xsl:template>
    
      <!-- Remove Empty Nodes -->
      <xsl:template match="*[.='']"/>
    
    </xsl:transform>
    

    输出

    <prefix:ct xmlns:prefix="http://www.example.com">
        <c>http://192.168.105.213</c>
        <l>http://192.168.105.213</l>
        <l>http://192.168.105.213</l>
        <o>http://192.168.105.213</o>
    </prefix:ct>
    

    【讨论】:

    • 我最初尝试使用 XSLT,使用与您提供的相同模板,但没有这部分 &lt;!-- Empty Template to Remove Such Nodes --&gt; &lt;xsl:template match="*[.='']"/&gt;,那里显示了空白区域。将尝试添加最后一部分。这会删除空格吗?
    • 基本上缩进的空白也被剥离了。
    • 是的,如图所示。事实上,模板匹配是脚本的关键项。身份转换会按原样复制整个文档,因此如果您不使用此空模板,则不会发生任何变化。还使用&lt;xsl:strip-space elements="*"/&gt; 删除不需要的空格。
    • Ok.. 如果我们只想移除特定名称的特定空元素,, , 是三个空的元素我只想删除一个和三个元素:
    • 查看 命名空间 的更新部分,您在 XSLT 的标头中声明命名空间并添加新模板。包括示例。另外——在询问 XML 问题时始终包含名称空间。此外,对于命名空间,这与正则表达式有关!
    猜你喜欢
    • 1970-01-01
    • 2012-02-24
    • 2011-07-28
    • 1970-01-01
    • 2011-05-24
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多