Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用XSLT替换XML属性中的换行符_Xml_Xslt_Xslt 2.0 - Fatal编程技术网

用XSLT替换XML属性中的换行符

用XSLT替换XML属性中的换行符,xml,xslt,xslt-2.0,Xml,Xslt,Xslt 2.0,我需要一些XSLT(或其他东西,请参见下文)来用替换字符替换所有属性中的换行符 我必须处理遗留XML,它将所有数据存储为属性,并使用新行表示基数。例如: <sample> <p att="John Paul Ringo"></p> </sample> 使用Saxon将以下内容应用于示例XML输出: John Paul Ringo 显然,这种格式不是我想要的-这只是为了试验replace()-但是在我们开始XSLT处理时,

我需要一些XSLT(或其他东西,请参见下文)来用替换字符替换所有属性中的换行符

我必须处理遗留XML,它将所有数据存储为属性,并使用新行表示基数。例如:

<sample>
    <p att="John
    Paul
    Ringo"></p>
</sample>
使用Saxon将以下内容应用于示例XML输出:

John Paul Ringo

显然,这种格式不是我想要的-这只是为了试验
replace()
-但是在我们开始XSLT处理时,换行符已经正常化了吗?如果是这样,是否有其他方法可以使用Java解析器将这些值解析为write?到目前为止,我只使用了JAXB。

这似乎很难做到。正如我在中发现的那样,属性中的新行字符是有效的,但XML解析器将其规范化(),因此它可能在处理之前(因此在替换之前)丢失。

XSLT仅在XML解析器处理完XML后才看到它,而XML解析器将完成属性值规范化

我认为一些XML解析器可以选择抑制属性值规范化。如果您不能访问这样的解析器,我认为用

可能是您的最佳逃生路线。以这种方式转义的换行不会因属性值规范化而飞溅。

我通过使用预处理XML解决了这个问题(这是对@Ian Roberts关于使用非XML工具解析XML的评论的认可)。JSoup是(或曾经是)为HTML文档设计的,但是在这种上下文中工作得很好

我的代码如下:

@测试
public void verifyNewlineEscaping(){
最终列表节点=Parser.parseXmlFragment(FileUtils.readFileToString(sourcePath.toFile(),“UTF-8”),“”);
fixAttributeNewlines(节点);
//重构XML
StringBuilder输出=新的StringBuilder();
用于(节点:节点){
append(node.toString());
}
//将清除的输出打印到标准输出
系统输出打印项次(输出);
}
/**
*将XML属性中的换行符和周围的空格替换为
*为了避免将换行符转换为单个空格时出现空白规范化。
* 
*
*如果将具有语义值的换行符错误地插入到
*属性值。
*

* *@param nodes要更新的节点 */ 私有静态void fixAttributeNewlines(最终列表节点){ /* *递归迭代XML文档中所有节点中的所有属性,执行 *属性字符串替换 */ 用于(最终节点:节点){ 最终列表属性=node.attributes().asList(); for(最终属性:属性){ //JSoup将空白报告为属性 如果(!StringUtils.isWhitespace(attribute.getValue())){ attribute.setValue(attribute.getValue().replaceAll(\\s*\r?\n\\s*,“|”); } } //递归处理子节点 如果(!node.childNodes().isEmpty()){ fixAttributeNewlines(node.childNodes()); } } }
对于我问题中的示例XML,此方法的输出为:

<sample> 
    <p att="John|Paul|Ringo"></p> 
</sample>


请注意,我没有使用

我有一种非常不愉快的感觉,我可能需要戴上橡皮手套,在解析XML字符串之前在XML字符串上实现一个肮脏的正则表达式。不幸的是,我无法控制XML的产生。实际上,不,这太可怕了。如果属性值中的空格在语义上是重要的,那么你就不是在处理XML,而你需要使用非XML工具来处理它。解析器必须将属性值中的所有换行符转换为空格,如果您希望在解析后看到的值中包含换行符,则必须将其转义为字符引用(
),我不同意您的看法。XML是从一个应用程序导出的,该应用程序将保持匿名。这并不完全是应用程序的错,尽管将所有数据填充到属性中可能是一种有点可疑的方法。我怀疑用户通过使用新行解决了这个特定领域缺乏1:M基数的问题,应用程序盲目地将新行导出为XML。我可能会对任何为可疑XML设计的Java库进行一些研究-这不可能是一个孤立的实例,所以我肯定有人故意编写了一个松散/宽容的解析器。我也看到了这一点,但我希望他们仍然会在那里进行一些XSLT修复。此后,我通过不声称自己是XML解析器发现了解决问题的方法,这可能会使它不必遵守XML规范。现在我来试一试……只要大声想一想,您就可以这样做
replace(/data/@value,'\s{2,10}','|')
-这不是绝对正确的,因为它依赖于将有多个空格而不是换行符,但它可以生成作业。@JirkaŠ。不,这是行不通的,因为XML解析器在数据到达XPath数据模型之前将属性值中所有连续的空格压缩到一个空格中。我担心这一点,但我在Altova中尝试过,它成功了。可能这只是Altova的特殊性。啊,我发现我错过了中的关键一句:“所有没有声明的属性都应该由非验证处理器处理,就像声明了CDATA一样。”-因此,如果没有DTD,解析器将用空格替换换行符,但不会将连续空格折叠为单个空格。谢谢Michael。在做了大量的挖掘之后,我想找出一个J
<sample> 
    <p att="John|Paul|Ringo"></p> 
</sample>