У меня есть некоторые данные xml с несколькими узлами Name. В зависимости от наличия или отсутствия узла id мне нужно разделить узлы. При преобразовании в JSON я хочу, чтобы все похожие узлы были объединены в массив JSON. Ниже приведены мои данные XML
<Names>
<CustName>
<Name>Name1</Name>
<id>3</id>
</CustName>
<CustName >
<Name>Name2</Name>
</CustName>
<CustName>
<Name>Name3</Name>
<id>32</id>
</CustName>
</Names>
XSLT, который я пробовал, выглядит следующим образом. Но это создает два узла для обновления и один узел для создания. Принимая во внимание, что я хочу, чтобы узлы 1st и 3rd Name находились в узле Update, а узел 2nd Name — в разделе Create
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output indent = "no" method = "xml" omit-xml-declaration = "yes"/>
<xsl:template match = "/">
<CustomerNames>
<xsl:for-each select = "//Names/CustName">
<xsl:choose>
<xsl:when test = "id !=''">
<Update>
<CustName>
<xsl:value-of select = "Name"/>
</CustName>
<id>
<xsl:value-of select = "id"/>
</id>
</Update>
</xsl:when>
<xsl:otherwise>
<Create>
<CustName>
<xsl:value-of select = "Name"/>
</CustName>
</Create>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</CustomerNames>
</xsl:template>
</xsl:stylesheet>
Преобразованный xml должен выглядеть так:
<CustomerNames>
<Update>
<CustName>Name1</CustName>
<id>3</id>
</Update>
<Update>
<CustName>Name3</CustName>
<id>32</id>
</Update>
<Create>
<Name>Name2</Name>
</Create>
</CustomerNames>
При преобразовании в json я хочу, чтобы аналогичные узлы добавлялись в массив. Так
{
"CustomerNames":{
"Update":[
{
"CustName":"Name1",
"id":"3"
},
{
"CustName":"Name3",
"id":"32"
}
],
"Create":[
{
"Name":"Name2"
}
]
}
}
Как я могу добиться этого в XSL 1.0?
Я не уверен, приведет ли полученный xml к желаемому json. При преобразовании в JSON мне нужен JSONArray, в котором все узлы Name принадлежат либо Update, либо Create.
Таблица стилей, которую вы уже создали, создает XML, который вы показываете, за исключением порядка узлов Update и Create.
Да, я знаю, что таблица стилей создает желаемый xml. Но при преобразовании в JSON я получаю 3 разных объекта: 2 для обновления и 1 для создания. Предположим, у меня есть 10 узлов, они будут производить 10 разных объектов. Я хочу 2 JSONArrays для создания и обновления. Update — это массив, состоящий из id, а Create — это массив без id. Можно ли этого добиться с помощью XSLT?
Я не знаю, какая логика используется для преобразования полученного XML в JSON. Поэтому я не знаю, каким должен быть результирующий XML. Поэтому я не знаю, как написать XSLT для его создания.
Кажется, порядок размещения узлов имеет значение при автоматическом преобразовании XML в JSON. Следовательно, обновите свой XSLT до чего-то вроде приведенного ниже.
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output indent = "no" method = "xml" omit-xml-declaration = "yes"/>
<xsl:template match = "/">
<CustomerNames>
<xsl:for-each select = "//Names/CustName[id]">
<Update>
<CustName>
<xsl:value-of select = "Name"/>
</CustName>
<id>
<xsl:value-of select = "id"/>
</id>
</Update>
</xsl:for-each>
<xsl:for-each select = "//Names/CustName[not(id)]">
<Create>
<CustName>
<xsl:value-of select = "Name"/>
</CustName>
</Create>
</xsl:for-each>
</CustomerNames>
</xsl:template>
</xsl:stylesheet>
Это работает, спасибо! Но есть ли способ добиться этого, используя один для каждого? Поскольку я заметил, что наличие 2 для каждого здесь увеличивает время отклика только для преобразования xml.
@Ruby есть разные способы сделать это. Цикл довольно эффективен, поскольку мы не перебираем все элементы в обоих for-each, но всегда есть накладные расходы на обход узла. Я добавил еще один альтернативный подход с одним для каждого. Взгляните на это. Но тем не менее, это будет иметь аналогичные накладные расходы, поскольку дерево XML нуждается в сортировке.
Кроме того, вы можете сгруппировать узлы XML с помощью сортировки XSL.
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output indent = "no" method = "xml" omit-xml-declaration = "yes"/>
<xsl:template match = "/">
<CustomerNames xmlns = "">
<xsl:for-each select = "//Names/CustName">
<xsl:sort select = "id"/>
<xsl:choose>
<xsl:when test = "id !=''">
<Update>
<CustName>
<xsl:value-of select = "Name"/>
</CustName>
<id>
<xsl:value-of select = "id"/>
</id>
</Update>
</xsl:when>
<xsl:otherwise>
<Create>
<CustName>
<xsl:value-of select = "Name"/>
</CustName>
</Create>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</CustomerNames>
</xsl:template>
</xsl:stylesheet>
Я попробовал этот подход сортировки и группировки. Но похоже, что я сортировал неправильный элемент.
@Ruby это решение очень тесно связано с вашим вариантом использования. Просто сортировка элементов Null и Not null.
Другой подход заключается в использовании посредника Payloadfactry после посредника XSLT для группировки узлов. Пример ниже.
<payloadFactory media-type = "xml">
<format>
<CustomerNames>
$1
$2
</CustomerNames>
</format>
<args>
<arg expression = "//Update"/>
<arg expression = "//Create"/>
</args>
</payloadFactory>
Ваша таблица стилей создает XML, а не JSON. Пожалуйста, опубликуйте точный ожидаемый результат в формате XML.