gpt4 book ai didi

xml - 从 XML 到 XML 文档的 XSLT 转换

转载 作者:行者123 更新时间:2023-12-04 04:41:14 24 4
gpt4 key购买 nike

我需要帮助来获得正确的 XSL 转换,我希望源 XML 按原样复制并对目标 XML 文件进行所需的更新。现在我正在尝试两件事,第一是将源复制到目标 XML,第二是更新根元素的命名空间 URL 和版本属性。请找到下面的代码,让我知道出了什么问题,因为我只在目标 xml 中获取根元素,内容丢失,根元素的结束标记丢失,并且属性版本没有更新。

源 XML-

<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v1="http://www.abc.com/s/v1.0">
<soapenv:Header/>
<soapenv:Body>
<v1:QueryRequest version="1">
<subject>
<dataList>
<!--1 or more repetitions:-->
<dataset>
<type>company</type>
<value>abc</value>
</dataset>
<dataset>
<type>user</type>
<value>xyz</value>
</dataset>
</dataList>
</subject>
<!--Optional:-->
<testList>
<!--1 or more repetitions:-->
<criteria>
<type>test</type>
<value>972</value>
</criteria>
<criteria>
<type>test2</type>
<value>false</value>
</criteria>
</testList>
</v1:QueryRequest>
</soapenv:Body>
</soapenv:Envelope>

XSL 文件:-
<?xml version="1.0" encoding="utf-8"?>
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:old="http://www.abc.com/s/v1.0" exclude-result-prefixes="old">
<xsl:output method="xml" encoding="utf-8" indent="yes" version="1.0" />

<xsl:param name="newversion" select="2.0"> </xsl:param>
<!-- replace namespace of elements in old namespace -->

<xsl:template match="old:*">
<xsl:element name="{local-name()}" namespace="http://www.abc.com/s/v2.0">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>

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

<xsl:template match="//*[local-name()='QueryRequest']/@version">
<xsl:attribute name="version">
<xsl:value-of select="$newversion"/>
</xsl:attribute>

</xsl:template>

使用上述 XSL 文件输出:-
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body><ns7:QueryRequest version="1" xmlns=""
xmlns:ns6="http://www.abc.com/s/v1.0"
xmlns:ns7="http://www.abc.com/s/v2.0"/>

</soapenv:Body>
</soapenv:Envelope>

"

预期输出:
<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v2="http://www.abc.com/s/v2.0">
<soapenv:Header/>
<soapenv:Body>
<v2:QueryRequest version="2.0">
<subject>
<dataList>
<!--1 or more repetitions:-->
<dataset>
<type>company</type>
<value>abc</value>
</dataset>
<dataset>
<type>user</type>
<value>xyz</value>
</dataset>
</dataList>
</subject>
<!--Optional:-->
<testList>
<!--1 or more repetitions:-->
<criteria>
<type>test</type>
<value>972</value>
</criteria>
<criteria>
<type>test2</type>
<value>false</value>
</criteria>
</testList>
</v2:QueryRequest>
</soapenv:Body>
</soapenv:Envelope>

触发此转换的 Spring config 代码 -
<int-xml:xslt-transformer  id="v2transformer"                                     xsl-resource="classpath:transformtoversion2.xslt" 
input-channel="AChannel" output-channel="BChannel"
result-transformer="resultTransformer">
</int-xml:xslt-transformer>

最佳答案

对我来说,一旦我通过将根元素重命名为 xsl:stylesheet 来更正 XSLT而不是 xsl:transform ,我得到几乎正确的输出

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://www.abc.com/s/v1.0">
<soapenv:Header/>
<soapenv:Body>
<QueryRequest xmlns="http://www.abc.com/s/v2.0" version="2">
<subject xmlns="">
<dataList>
<!--1 or more repetitions:-->
<dataset>
<type>company</type>
<value>abc</value>
</dataset>
<dataset>
<type>user</type>
<value>xyz</value>
</dataset>
</dataList>
</subject>
<!--Optional:-->
<testList xmlns="">
<!--1 or more repetitions:-->
<criteria>
<type>test</type>
<value>972</value>
</criteria>
<criteria>
<type>test2</type>
<value>false</value>
</criteria>
</testList>
</QueryRequest>
</soapenv:Body>
</soapenv:Envelope>

与您需要的唯一语义上的显着区别是 version="2"而不是 version="2.0" ,可以通过添加一些引号来修复
<xsl:param name="newversion" select="'2.0'" />

将参数值设置为字符串 2.0 而不是数字 2。

对于外观差异,如果要删除未使用的 xmlns:v1来自根元素并使用 QueryRequest 的前缀元素而不是默认命名空间(然后由 xmlns="" 为 child 取消),那么你需要更像这样的东西
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:old="http://www.abc.com/s/v1.0" exclude-result-prefixes="old"
xmlns:v2="http://www.abc.com/s/v2.0">
<xsl:output method="xml" encoding="utf-8" indent="yes" version="1.0" />

<xsl:param name="newversion" select="'2.0'"/>

<!-- fix namespace declarations on root element -->
<xsl:template match="/*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<!-- copy the v2: binding from the stylesheet document -->
<xsl:copy-of select="document('')/xsl:stylesheet/namespace::v2" />
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>

<!-- replace namespace of elements in old namespace -->
<xsl:template match="old:*">
<xsl:element name="v2:{local-name()}">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>

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

<xsl:template match="old:QueryRequest/@version">
<xsl:attribute name="version">
<xsl:value-of select="$newversion"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>

我用 <xsl:element>而不是 <xsl:copy>/*模板因为 copy从原始标签复制命名空间绑定(bind)。

从评论中,您现在想要将所有 <type> 大写。值(value)观。您只需添加一个额外的模板即可实现此目的
<xsl:template match="type/text()">
<xsl:value-of select="translate(., 'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
</xsl:template>

没有简单的 to-upper-case XPath 1.0 中的函数,但您可以使用 translate(X, Y, Z) ,它通过字符串 X 将 Y 中的每个字符替换为 Z 中相同位置的字符。

这将转换所有 type元素,如果您只想转换数据集类型而不是标准类型,那么只需使用更具体的 match="dataset/type/text()" .

关于xml - 从 XML 到 XML 文档的 XSLT 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18856051/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com