GET 请求 XML 响应解析使用 XPath 生成 JS Object
GET Request XML response parsing using XPath to produce a JS Object
问题是我从对 WMS 服务器的 GET 请求得到“application/xml”响应,然后我使用 DOMParser().parseFromString() 方法使用 XPath 表达式进行解析。我尝试查看不同的解决方案,如专用库,但我发现了 XPath 表达式,现在我需要帮助编写一个 XPath 表达式,它将 return 我层标记的名称和 XML 响应的标题看起来喜欢
<Layer>
<Title>Title Level 1</Title>
<Name>Name Level 1</Name>
<Layer>
<Title>Title Level 2</Title>
<Name>Name Level 2</Name>
<Layer>
<Title>Title Level 3-1</Title>
<Name>Name Level 3-1</Name>
</Layer>
<Layer>
<Title>Title Level 3-2</Title>
<Name>Name Level 3-2</Name>
</Layer>
</Layer>
</Layer>
然后 return 我 JSON
{
title: 'Title Level 1'
name: 'Name Level 1'
children: [
{
title: 'Title Level 2'
name: 'Name Level 2'
children: [
{
title: 'Title Level 3-1'
name: 'Name Level 3-1'
},
{
title: 'Title Level 3-1'
name: 'Name Level 3-1'
}
]
]
}
您可以在浏览器中使用 XSLT 3 和 Saxon-JS 2 (https://www.saxonica.com/download/javascript.xml) 将 XML 转换为 JSON:
const xml = `<Layer>
<Title>Title Level 1</Title>
<Name>Name Level 1</Name>
<Layer>
<Title>Title Level 2</Title>
<Name>Name Level 2</Name>
<Layer>
<Title>Title Level 3-1</Title>
<Name>Name Level 3-1</Name>
</Layer>
<Layer>
<Title>Title Level 3-2</Title>
<Name>Name Level 3-2</Name>
</Layer>
</Layer>
</Layer>`;
const xslt = `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns="http://www.w3.org/2005/xpath-functions"
expand-text="yes"
version="3.0">
<xsl:output method="json" build-tree="no"/>
<xsl:template match="/*" priority="5">
<xsl:variable name="json-xml">
<map>
<xsl:apply-templates/>
</map>
</xsl:variable>
<xsl:sequence select="xml-to-json($json-xml) => parse-json()"/>
</xsl:template>
<xsl:template match="*[not(*)]">
<string key="{local-name()}">{.}</string>
</xsl:template>
<xsl:template match="Layer[1]">
<array key="children">
<xsl:apply-templates select="../Layer" mode="map"/>
</array>
</xsl:template>
<xsl:template match="Layer[position() > 1]"/>
<xsl:template match="Layer" mode="map">
<map>
<xsl:apply-templates/>
</map>
</xsl:template>
</xsl:stylesheet>`;
const jsonResult = SaxonJS.XPath.evaluate(`transform(map { 'source-node' : parse-xml($xml), 'stylesheet-text' : $xslt, 'delivery-format' : 'raw' })?output`, [], { 'params' : { 'xml' : xml, 'xslt' : xslt } });
console.log(jsonResult);
<script src="https://xsltfiddle-beta.liberty-development.net/js/SaxonJS2/SaxonJS2.js"></script>
一种略有不同但可能更紧凑的 XSLT 3 方法是将 XML 直接转换为映射和数组输出作为 JSON 对象和数组:
const xml = `<Layer>
<Title>Title Level 1</Title>
<Name>Name Level 1</Name>
<Layer>
<Title>Title Level 2</Title>
<Name>Name Level 2</Name>
<Layer>
<Title>Title Level 3-1</Title>
<Name>Name Level 3-1</Name>
</Layer>
<Layer>
<Title>Title Level 3-2</Title>
<Name>Name Level 3-2</Name>
</Layer>
</Layer>
</Layer>`;
const xslt = `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns="http://www.w3.org/2005/xpath-functions"
xmlns:mf="http://example.com/mf"
expand-text="yes"
version="3.0">
<xsl:strip-space elements="*"/>
<xsl:output method="json" build-tree="no" indent="yes"/>
<xsl:template match="/Layer" priority="5">
<xsl:map>
<xsl:apply-templates/>
</xsl:map>
</xsl:template>
<xsl:template match="*[not(*)]">
<xsl:map-entry key="local-name()" select="data()"/>
</xsl:template>
<xsl:template match="Layer[1]">
<xsl:map-entry key="'children'">
<xsl:sequence select="array { ../Layer/mf:apply-templates(.) }"/>
</xsl:map-entry>
</xsl:template>
<xsl:template match="Layer[position() > 1]"/>
<xsl:function name="mf:apply-templates" as="item()*">
<xsl:param name="elements" as="element(*)*"/>
<xsl:map>
<xsl:apply-templates select="$elements/*"/>
</xsl:map>
</xsl:function>
</xsl:stylesheet>`;
const jsonResult = SaxonJS.XPath.evaluate(`
transform(
map {
'source-node' : parse-xml($xml),
'stylesheet-text' : $xslt,
'delivery-format' : 'raw'
}
)?output`,
[],
{ 'params' : { 'xml' : xml, 'xslt' : xslt } }
);
console.log(jsonResult);
<script src="https://xsltfiddle-beta.liberty-development.net/js/SaxonJS2/SaxonJS2.js"></script>
在两个示例中,为了简洁(以及可执行的单个 Whosebug 代码片段的优雅),我使用 XPath 3.1 transform
函数直接从 JavaScript 到 运行 XSLT 3 代码;虽然 Saxon-JS 2 在浏览器和 Node.js 中都完美支持,但应该注意的是,出于性能原因,如果您开发并修复了 XSLT,推荐的方法是使用 Saxon EE 进行预编译或使用 Saxon JS 2 的 xslt3
命令行从 XSLT 到 SEF(即从基于 XML 的 XSLT 代码到基于 JSON 的 SEF 格式)以便 SEF 可以直接馈送到 transform
Saxon JS 中的函数 API https://www.saxonica.com/saxon-js/documentation/index.html#!api/transform。在现实世界中,这应该比使用 SaxonJS.XPath.evaluate
表现得更好,并且在 Node.js 上还允许您使用异步编程。
问题是我从对 WMS 服务器的 GET 请求得到“application/xml”响应,然后我使用 DOMParser().parseFromString() 方法使用 XPath 表达式进行解析。我尝试查看不同的解决方案,如专用库,但我发现了 XPath 表达式,现在我需要帮助编写一个 XPath 表达式,它将 return 我层标记的名称和 XML 响应的标题看起来喜欢
<Layer>
<Title>Title Level 1</Title>
<Name>Name Level 1</Name>
<Layer>
<Title>Title Level 2</Title>
<Name>Name Level 2</Name>
<Layer>
<Title>Title Level 3-1</Title>
<Name>Name Level 3-1</Name>
</Layer>
<Layer>
<Title>Title Level 3-2</Title>
<Name>Name Level 3-2</Name>
</Layer>
</Layer>
</Layer>
然后 return 我 JSON
{
title: 'Title Level 1'
name: 'Name Level 1'
children: [
{
title: 'Title Level 2'
name: 'Name Level 2'
children: [
{
title: 'Title Level 3-1'
name: 'Name Level 3-1'
},
{
title: 'Title Level 3-1'
name: 'Name Level 3-1'
}
]
]
}
您可以在浏览器中使用 XSLT 3 和 Saxon-JS 2 (https://www.saxonica.com/download/javascript.xml) 将 XML 转换为 JSON:
const xml = `<Layer>
<Title>Title Level 1</Title>
<Name>Name Level 1</Name>
<Layer>
<Title>Title Level 2</Title>
<Name>Name Level 2</Name>
<Layer>
<Title>Title Level 3-1</Title>
<Name>Name Level 3-1</Name>
</Layer>
<Layer>
<Title>Title Level 3-2</Title>
<Name>Name Level 3-2</Name>
</Layer>
</Layer>
</Layer>`;
const xslt = `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns="http://www.w3.org/2005/xpath-functions"
expand-text="yes"
version="3.0">
<xsl:output method="json" build-tree="no"/>
<xsl:template match="/*" priority="5">
<xsl:variable name="json-xml">
<map>
<xsl:apply-templates/>
</map>
</xsl:variable>
<xsl:sequence select="xml-to-json($json-xml) => parse-json()"/>
</xsl:template>
<xsl:template match="*[not(*)]">
<string key="{local-name()}">{.}</string>
</xsl:template>
<xsl:template match="Layer[1]">
<array key="children">
<xsl:apply-templates select="../Layer" mode="map"/>
</array>
</xsl:template>
<xsl:template match="Layer[position() > 1]"/>
<xsl:template match="Layer" mode="map">
<map>
<xsl:apply-templates/>
</map>
</xsl:template>
</xsl:stylesheet>`;
const jsonResult = SaxonJS.XPath.evaluate(`transform(map { 'source-node' : parse-xml($xml), 'stylesheet-text' : $xslt, 'delivery-format' : 'raw' })?output`, [], { 'params' : { 'xml' : xml, 'xslt' : xslt } });
console.log(jsonResult);
<script src="https://xsltfiddle-beta.liberty-development.net/js/SaxonJS2/SaxonJS2.js"></script>
一种略有不同但可能更紧凑的 XSLT 3 方法是将 XML 直接转换为映射和数组输出作为 JSON 对象和数组:
const xml = `<Layer>
<Title>Title Level 1</Title>
<Name>Name Level 1</Name>
<Layer>
<Title>Title Level 2</Title>
<Name>Name Level 2</Name>
<Layer>
<Title>Title Level 3-1</Title>
<Name>Name Level 3-1</Name>
</Layer>
<Layer>
<Title>Title Level 3-2</Title>
<Name>Name Level 3-2</Name>
</Layer>
</Layer>
</Layer>`;
const xslt = `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns="http://www.w3.org/2005/xpath-functions"
xmlns:mf="http://example.com/mf"
expand-text="yes"
version="3.0">
<xsl:strip-space elements="*"/>
<xsl:output method="json" build-tree="no" indent="yes"/>
<xsl:template match="/Layer" priority="5">
<xsl:map>
<xsl:apply-templates/>
</xsl:map>
</xsl:template>
<xsl:template match="*[not(*)]">
<xsl:map-entry key="local-name()" select="data()"/>
</xsl:template>
<xsl:template match="Layer[1]">
<xsl:map-entry key="'children'">
<xsl:sequence select="array { ../Layer/mf:apply-templates(.) }"/>
</xsl:map-entry>
</xsl:template>
<xsl:template match="Layer[position() > 1]"/>
<xsl:function name="mf:apply-templates" as="item()*">
<xsl:param name="elements" as="element(*)*"/>
<xsl:map>
<xsl:apply-templates select="$elements/*"/>
</xsl:map>
</xsl:function>
</xsl:stylesheet>`;
const jsonResult = SaxonJS.XPath.evaluate(`
transform(
map {
'source-node' : parse-xml($xml),
'stylesheet-text' : $xslt,
'delivery-format' : 'raw'
}
)?output`,
[],
{ 'params' : { 'xml' : xml, 'xslt' : xslt } }
);
console.log(jsonResult);
<script src="https://xsltfiddle-beta.liberty-development.net/js/SaxonJS2/SaxonJS2.js"></script>
在两个示例中,为了简洁(以及可执行的单个 Whosebug 代码片段的优雅),我使用 XPath 3.1 transform
函数直接从 JavaScript 到 运行 XSLT 3 代码;虽然 Saxon-JS 2 在浏览器和 Node.js 中都完美支持,但应该注意的是,出于性能原因,如果您开发并修复了 XSLT,推荐的方法是使用 Saxon EE 进行预编译或使用 Saxon JS 2 的 xslt3
命令行从 XSLT 到 SEF(即从基于 XML 的 XSLT 代码到基于 JSON 的 SEF 格式)以便 SEF 可以直接馈送到 transform
Saxon JS 中的函数 API https://www.saxonica.com/saxon-js/documentation/index.html#!api/transform。在现实世界中,这应该比使用 SaxonJS.XPath.evaluate
表现得更好,并且在 Node.js 上还允许您使用异步编程。