草庐IT

XML 和 XSLT 保留 CDATA

coder 2024-07-04 原文

我正在从事一个项目,其中包括在 xml 上应用一些 xslt。

我的输入 xml 在任何 xml 节点中包含“CDATA”。

现在我想要的是它应该保留“CDATA”,如果它有输入的话

我尝试了很多解决方案,例如禁用输出转义和 cdata-section-elements 等... 但我发现它们都不适合我的要求。

那么,有什么办法可以做到吗??如果输入 xml 节点有 cdata 那么它应该在输出中给出它如果输入 xml 节点没有 cdata 那么它不应该在输出中给出它。

我有一个名为节点的节点,它包含 cdata,另一个节点位于某个不包含 cdata 的 diff 位置..

<Address>
<Location>
<Code>912</Code>
<Value>10301</Value>
</Location>
<Name><![CDATA[E&S]]></Name>
<CompanyName><![CDATA[E&S]]></CompanyName>
<AddressLine3>dummy address</AddressLine3>
<City>dummy city</City>
<State>dummy state</State>
<PostalCode>dummy postal code</PostalCode>
<Country>dummy country</Country>
</Address>
<Nodes>
<Node>
<Type>CTU</Type>
<Text><![CDATA[dummy text & dummy Text.]]></Text>
</Node>
</Nodes>

只有预定义的节点才会包含 cdata 是不固定的,它可以出现在任何地方

最佳答案

XSLT 使用的 XPath 数据模型不允许区分任何 CDATA 部分——其中任何部分都表示为文本节点(的一部分)。所以 CDATA 保存不能完全普遍地单独使用 XSLT 或 XPath 来实现。它可以通过基于 DOM 的方法来实现。

如果在转换的输出中,具有特定名称的元素的文本节点需要 CDATA 部分,而其他元素则不需要,那么这可以在 XSLT 中指定 cdata-section-elements 来完成<xsl:output> 中的属性声明。

这是一个如何完成的简短示例:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"
 cdata-section-elements="a b c d e"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时:

<Record>
    <a>10:30</a>
    <b>20:30</b>
    <c>10:60</c>
    <d>1:15</d>
    <e>1:03</e>
</Record>

产生了想要的、正确的结果:

<Record>
   <a><![CDATA[10:30]]></a>
   <b><![CDATA[20:30]]></b>
   <c><![CDATA[10:60]]></c>
   <d><![CDATA[1:15]]></d>
   <e><![CDATA[1:03]]></e>
</Record>

如果事先不知道元素名称集,可以使用生成另一个样式表的样式表,最终应将其应用于 XML 文档以生成所需结果:

<xsl:stylesheet version="1.0" xmlns:x="http://www.w3.org/1999/XSL/Transform"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xxx="xxx">
 <xsl:namespace-alias stylesheet-prefix="xxx" result-prefix="xsl"/>
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kElemByName" match="*[text()[normalize-space()]]" use="name()"/>

 <xsl:variable name="vDistinctNamedElems" select=
 "//*[generate-id()=generate-id(key('kElemByName',name())[1])]"/>

 <xsl:variable name="vDistinctNames">
  <xsl:for-each select="$vDistinctNamedElems">
   <xsl:value-of select="concat(name(), ' ')"/>
  </xsl:for-each>
 </xsl:variable>

 <xsl:template match="node()|@*">
  <xxx:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xxx:output omit-xml-declaration="yes" indent="yes"
       cdata-section-elements="{$vDistinctNames}"/>
    <xxx:strip-space elements="*"/>

    <xxx:template match="node()|@*">
     <xxx:copy>
       <xxx:apply-templates select="node()|@*"/>
     </xxx:copy>
    </xxx:template>
  </xxx:stylesheet>
 </xsl:template>
</xsl:stylesheet>

当这个转换应用于同一个 XML 文档时(如上),结果是另一个 XSLT 样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:x="http://www.w3.org/1999/XSL/Transform"
                version="1.0">
   <xsl:output omit-xml-declaration="yes" indent="yes" cdata-section-elements="a b c d e "/>
   <xsl:strip-space elements="*"/>
   <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

在此样式表中,cdata-section-elements 中的所有元素名称属性,是动态生成的(使用 Muenchian 方法进行分组)。

当我们最终将如此生成的 XSLT 样式表应用于同一个 XML 文档时,我们得到了想要的结果:

<Record>
   <a><![CDATA[10:30]]></a>
   <b><![CDATA[20:30]]></b>
   <c><![CDATA[10:60]]></c>
   <d><![CDATA[1:15]]></d>
   <e><![CDATA[1:03]]></e>
</Record>

解释:

  1. 动态生成新的转换,使用 XSLT 指令 xsl:namespace-alias .

  2. Muenchian grouping 以确定所有不同的元素名称。

关于XML 和 XSLT 保留 CDATA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15697433/

有关XML 和 XSLT 保留 CDATA的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  2. ruby-on-rails - 如何在 Rails 3 中禁用 XML 解析 - 2

    我想禁用HTTP参数的自动XML解析。但我发现命令仅适用于Rails2.x,它们都不适用于3.0:config.action_controller.param_parsers.deleteMime::XML(application.rb)ActionController::Base.param_parsers.deleteMime::XMLRails3.0中的等价物是什么? 最佳答案 根据CVE-2013-0156的最新安全公告你可以将它用于Rails3.0。3.1和3.2ActionDispatch::ParamsParser::

  3. ruby - 如何使用 Nokogiri::XML::Builder 生成动态标签? - 2

    我正在遍历数组中的一组标签名称,我想使用构建器打印每个标签名称,而不是求助于“我认为:builder=Nokogiri::XML::Builder.newdo|xml|fortagintagsxml.tag!tag,somevalendend会这样做,但它只是创建名称为“tag”的标签,并将标签变量作为元素的文本值。有人可以帮忙吗?这个看起来应该比较简单,我刚刚在搜索引擎上找不到答案。我可能没有以正确的方式提问。 最佳答案 尝试以下操作。如果我没记错的话,我添加了一个根节点,因为Nokogiri需要一个。builder=Nokogi

  4. ruby - 如何让 Nokogiri 解析并返回 XML 文档? - 2

    这是一些奇怪的例子:#!/usr/bin/rubyrequire'rubygems'require'open-uri'require'nokogiri'print"withoutread:",Nokogiri(open('http://weblog.rubyonrails.org/')).class,"\n"print"withread:",Nokogiri(open('http://weblog.rubyonrails.org/').read).class,"\n"运行此返回:withoutread:Nokogiri::XML::Documentwithread:Nokogiri::

  5. ruby - 模式加载时出现 Nokogiri::XML::Schema SyntaxError - 2

    我正在尝试加载SAML协议(protocol)架构(具体来说:https://www.oasis-open.org/committees/download.php/3407/oasis-sstc-saml-schema-protocol-1.1.xsd),但在执行此操作之后:schema=Nokogiri::XML::Schema(File.read('saml11_schema.xsd'))我得到这个输出:Nokogiri::XML::SyntaxErrorException:Element'{http://www.w3.org/2001/XMLSchema}element',att

  6. ruby - 为什么 Ruby 在抛出 NameError 异常后仍保留代码求值? - 2

    我无法向自己解释的简单代码:putsaifa=1这导致warning:found=inconditional,shouldbe==NameError:undefinedlocalvariableormethod'a'formain:Object不过,现在检查a我们可以看到,它已被定义:a#=>1尽管抛出异常,为什么a仍被分配给1?来自docs:Theconfusioncomesfromtheout-of-orderexecutionoftheexpression.Firstthelocalvariableisassigned-tothenyouattempttocallanonexis

  7. ruby - whenever gem 能否保留 crontab 文件中的现有行? - 2

    我正在使用:ruby1.9.2每当0.7.2Capistrano2.9.0capistrano-ext1.2.1我在部署时与Capistrano结合使用来管理我的crontab文件。我注意到它每次都会完全重写我的crontab文件。我希望能够在cron中设置环境变量来控制PATH和MAILTO设置,它们是常规的cron环境变量。有没有办法让whenever不覆盖整个crontab文件,以便我可以将自定义添加到我的crontab文件并确保它们会持续存在? 最佳答案 是的,你可以做到这一点。您只需要为写入crontab的任务分配一个标识

  8. ruby - "begin"和 "end"是不是保留字? - 2

    我对Ruby中的保留字有点困惑。Matz与人合着的《TheRubyProgrammingLanguage》说begin和end是语言的保留字。它们肯定在句法上用于标记block。但是,该语言中的范围对象具有名为begin和end的方法,如(1..10).end=>10现在,对此进行测试,我发现我确实可以在对象上定义名为“begin”和“end”的方法,但如果我尝试将变量命名为“begin”,它会失败。(这里有一个使用它作为方法名的示例,它确实有效......:)classFoodefbeginputs"hi"endendFoo.new.begin所以,我想我是在问,像这样的保留字的实际

  9. ruby - 在 Ruby 哈希中查找保留重复项 - 2

    我有一个散列数组,我需要在其中根据散列之间的一个匹配值查找和存储匹配项。a=[{:id=>1,:name=>"Jim",:email=>"jim@jim.jim"},{:id=>2,:name=>"Paul",:email=>"paul@paul.paul"},{:id=>3,:name=>"Tom",:email=>"tom@tom.tom"},{:id=>1,:name=>"Jim",:email=>"jim@jim.jim"},{:id=>5,:name=>"Tom",:email=>"tom@tom.tom"},{:id=>6,:name=>"Jim",:email=>"jim

  10. ruby - 我们如何访问/操作与 byebug 保留关键字冲突的变量名? - 2

    我们如何访问那些与byebug保留名称冲突的变量名称?(byebug)varlocalh={"hierarchyId"=>"59f0b029e4b037ef11a055f7","level"=>2,...self=(byebug)我想访问变量“h”但键入h会显示“byebug的帮助对话框”(byebug)hbreak--Setsbreakpointsinthesourcecodecatch--Handlesexceptioncatchpointscondition--Setsconditionsonbreakpointscontinue--Runsuntilprogramends,hi

随机推荐