使用 VTD-XML 删除属性时如何 trim 元素名称

How to trim element name when removing attributes with VTD-XML

给出以下 xml 片段

<l:Variable xmlns="ddi:instance:3_2" xmlns:g="ddi:group:3_2" xmlns:l="ddi:logicalproduct:3_2" xmlns:r="ddi:reusable:3_2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <!-- some more content --!>
</l:Variable>

使用 VTD-XML 删除名称空间属性对以下代码段效果很好:

private String removeNamespaces( String xml )
{
    try
    {
        VTDGen generator = new VTDGen();
        generator.setDoc( xml.getBytes() );
        generator.parse( false );
        VTDNav navigator = generator.getNav();
        XMLModifier xm = new XMLModifier( navigator );
        AutoPilot autoPilot = new AutoPilot( navigator );
        autoPilot.selectXPath( "@*" );
        int i = -1;
        while ((i = autoPilot.evalXPath()) != -1)
        {
            if ( navigator.toString( i ).startsWith( "xmlns" ) )
            {
                xm.removeAttribute( i );
            }
        }
        XMLByteOutputStream xbos = new XMLByteOutputStream( xm.getUpdatedDocumentSize() );
        xm.output( xbos );
        return new String( xbos.getXML() );
    }
    catch (Exception e)
    {
        throw new RuntimeException( e );
    }
}

结果显示元素没有属性但中间的空格没有被删除:

<l:Variable     >
    <!-- some more content --!>
</l:Variable>

navigator.expandWhiteSpaces( l ) 等人的用法。不起作用,因为这些方法适用于元素而不适用于属性。

总结一下:是否可以删除属性以获得类似

的结果
<l:Variable>
    <!-- some more content --!>
</l:Variable>

首先,我认为您可以使用以下两种方式之一更简洁地编码 "starts-with"... 第一个使用了starts-with()的xpath函数。它在技术上是一个 xpath 2.0 函数,但它们在 vtd-xml 的 xpath 实现中受支持。连同 contains() 和 ends-with()...

        generator.parse( false );
        VTDNav navigator = generator.getNav();
        XMLModifier xm = new XMLModifier( navigator );
        AutoPilot autoPilot = new AutoPilot( navigator );
        autoPilot.selectXPath( "@*[starts-with(.,'xmlns')]" );
        int i = -1;
        while ((i = autoPilot.evalXPath()) != -1)
        {
           // if ( navigator.toString( i ).startsWith( "xmlns" ) )
            //{
                xm.removeAttribute( navigator.trimWhiteSpaces(i) );
            //}
        }

或者您可以直接使用 VTDNav 的 startWith、contains 或 endWith 函数,而不是显式地创建一个字符串对象 (navigator.toString)

VTDNav navigator = generator.getNav();
        XMLModifier xm = new XMLModifier( navigator );
        AutoPilot autoPilot = new AutoPilot( navigator );
        autoPilot.selectXPath( "@*" );
        int i = -1;
        while ((i = autoPilot.evalXPath()) != -1)
        {
           // if ( navigator.toString( i ).startsWith( "xmlns" ) )
            //{
            if (navigator.startsWith(i, "xmlns"))
                xm.removeAttribute( i );
            //}
        }

无论哪种方式,我认为在属性 name-value 对段上应用 expandWhitespace 可能有点危险,因为您可能会不小心删除定界空白并弄乱 well-formed xml 文档...

目前,清理 throw-away 个空格是 work-in-progress。我希望这不是一个表演障碍。如果是这样,您将不得不手动完成……这将是一个有点乏味的编码。但你必须

  1. 找到属性名称值段的开始和结束偏移量

  2. 将起始偏移量和长度编码为 64 位整数。

  3. 使用正确的参数调用 trimWhitespace 以删除末尾多余的空格...

vtd-xml-author 提示的启发,我现在的解决方法片段是

while ((i = autoPilot.evalXPath()) != -1)
{
    xm.removeAttribute( i );
    xm.removeContent( navigator.getTokenOffset( i ) - 1, 1 );
}

这假设属性的前导空白属于它,因此也被删除。所有其他空白将被忽略并保持不变。